summaryrefslogtreecommitdiff
path: root/flang/include/flang/Optimizer/Support/InternalNames.h
blob: f3f9fe70518935905d3a8d74c95f9710060511db (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
//===-- Optimizer/Support/InternalNames.h -----------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef FORTRAN_OPTIMIZER_SUPPORT_INTERNALNAMES_H
#define FORTRAN_OPTIMIZER_SUPPORT_INTERNALNAMES_H

#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include <cstdint>
#include <optional>

static constexpr llvm::StringRef typeDescriptorSeparator = ".dt.";
static constexpr llvm::StringRef bindingTableSeparator = ".v.";
static constexpr llvm::StringRef boxprocSuffix = "UnboxProc";

namespace fir {

/// Internal name mangling of identifiers
///
/// In order to generate symbolically referencable artifacts in a ModuleOp,
/// it is required that those symbols be uniqued.  This is a simple interface
/// for converting Fortran symbols into unique names.
///
/// This is intentionally bijective. Given a symbol's parse name, type, and
/// scope-like information, we can generate a uniqued (mangled) name.  Given a
/// uniqued name, we can return the symbol parse name, type of the symbol, and
/// any scope-like information for that symbol.
struct NameUniquer {
  enum class IntrinsicType { CHARACTER, COMPLEX, INTEGER, LOGICAL, REAL };

  /// The sort of the unique name
  enum class NameKind {
    NOT_UNIQUED,
    BLOCK_DATA_NAME,
    COMMON,
    CONSTANT,
    DERIVED_TYPE,
    DISPATCH_TABLE,
    GENERATED,
    INTRINSIC_TYPE_DESC,
    NAMELIST_GROUP,
    PROCEDURE,
    TYPE_DESC,
    VARIABLE
  };

  /// Components of an unparsed unique name
  struct DeconstructedName {
    DeconstructedName(llvm::StringRef name) : name{name} {}
    DeconstructedName(llvm::ArrayRef<std::string> modules,
                      llvm::ArrayRef<std::string> procs, std::int64_t blockId,
                      llvm::StringRef name, llvm::ArrayRef<std::int64_t> kinds)
        : modules{modules.begin(), modules.end()}, procs{procs.begin(),
                                                         procs.end()},
          blockId{blockId}, name{name}, kinds{kinds.begin(), kinds.end()} {}

    llvm::SmallVector<std::string> modules;
    llvm::SmallVector<std::string> procs;
    std::int64_t blockId;
    std::string name;
    llvm::SmallVector<std::int64_t> kinds;
  };

  /// Unique a common block name
  static std::string doCommonBlock(llvm::StringRef name);

  /// Unique a (global) constant name
  static std::string doConstant(llvm::ArrayRef<llvm::StringRef> modules,
                                llvm::ArrayRef<llvm::StringRef> procs,
                                std::int64_t block, llvm::StringRef name);

  /// Unique a dispatch table name
  static std::string doDispatchTable(llvm::ArrayRef<llvm::StringRef> modules,
                                     llvm::ArrayRef<llvm::StringRef> procs,
                                     std::int64_t block, llvm::StringRef name,
                                     llvm::ArrayRef<std::int64_t> kinds);

  /// Unique a compiler generated name without scope context.
  static std::string doGenerated(llvm::StringRef name);
  /// Unique a compiler generated name with scope context.
  static std::string doGenerated(llvm::ArrayRef<llvm::StringRef> modules,
                                 llvm::ArrayRef<llvm::StringRef> procs,
                                 std::int64_t blockId, llvm::StringRef name);

  /// Unique an intrinsic type descriptor
  static std::string
  doIntrinsicTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,
                            llvm::ArrayRef<llvm::StringRef> procs,
                            std::int64_t block, IntrinsicType type,
                            std::int64_t kind);

  /// Unique a procedure name
  static std::string doProcedure(llvm::ArrayRef<llvm::StringRef> modules,
                                 llvm::ArrayRef<llvm::StringRef> procs,
                                 llvm::StringRef name);

  /// Unique a derived type name
  static std::string doType(llvm::ArrayRef<llvm::StringRef> modules,
                            llvm::ArrayRef<llvm::StringRef> procs,
                            std::int64_t block, llvm::StringRef name,
                            llvm::ArrayRef<std::int64_t> kinds);

  /// Unique a (derived) type descriptor name
  static std::string doTypeDescriptor(llvm::ArrayRef<llvm::StringRef> modules,
                                      llvm::ArrayRef<llvm::StringRef> procs,
                                      std::int64_t block, llvm::StringRef name,
                                      llvm::ArrayRef<std::int64_t> kinds);
  static std::string doTypeDescriptor(llvm::ArrayRef<std::string> modules,
                                      llvm::ArrayRef<std::string> procs,
                                      std::int64_t block, llvm::StringRef name,
                                      llvm::ArrayRef<std::int64_t> kinds);

  /// Unique a (global) variable name. A variable with save attribute
  /// defined inside a subprogram also needs to be handled here
  static std::string doVariable(llvm::ArrayRef<llvm::StringRef> modules,
                                llvm::ArrayRef<llvm::StringRef> procs,
                                std::int64_t block, llvm::StringRef name);

  /// Unique a namelist group name
  static std::string doNamelistGroup(llvm::ArrayRef<llvm::StringRef> modules,
                                     llvm::ArrayRef<llvm::StringRef> procs,
                                     llvm::StringRef name);

  /// Entry point for the PROGRAM (called by the runtime)
  /// Can be overridden with the `--main-entry-name=<name>` option.
  static llvm::StringRef doProgramEntry();

  /// Decompose `uniquedName` into the parse name, symbol type, and scope info
  static std::pair<NameKind, DeconstructedName>
  deconstruct(llvm::StringRef uniquedName);

  /// Check if the name is an external facing name.
  static bool isExternalFacingUniquedName(
      const std::pair<NameKind, DeconstructedName> &deconstructResult);

  /// Check whether the name should be re-mangle with external ABI convention.
  static bool needExternalNameMangling(llvm::StringRef uniquedName);

  /// Does \p uniquedName belong to module \p moduleName?
  static bool belongsToModule(llvm::StringRef uniquedName,
                              llvm::StringRef moduleName);

  /// Given a mangled derived type name, get the name of the related derived
  /// type descriptor object. Returns an empty string if \p mangledTypeName is
  /// not a valid mangled derived type name.
  static std::string getTypeDescriptorName(llvm::StringRef mangledTypeName);

  /// Given a mangled derived type name, get the name of the related binding
  /// table object. Returns an empty string if \p mangledTypeName is not a valid
  /// mangled derived type name.
  static std::string
  getTypeDescriptorBindingTableName(llvm::StringRef mangledTypeName);

private:
  static std::string intAsString(std::int64_t i);
  static std::string doKind(std::int64_t kind);
  static std::string doKinds(llvm::ArrayRef<std::int64_t> kinds);
  static std::string toLower(llvm::StringRef name);

  NameUniquer() = delete;
  NameUniquer(const NameUniquer &) = delete;
  NameUniquer(NameUniquer &&) = delete;
  NameUniquer &operator=(const NameUniquer &) = delete;
};

} // namespace fir

#endif // FORTRAN_OPTIMIZER_SUPPORT_INTERNALNAMES_H