1//===- MCSymbolWasm.h -  ----------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8#ifndef LLVM_MC_MCSYMBOLWASM_H
9#define LLVM_MC_MCSYMBOLWASM_H
10
11#include "llvm/BinaryFormat/Wasm.h"
12#include "llvm/MC/MCSymbol.h"
13
14namespace llvm {
15
16class MCSymbolWasm : public MCSymbol {
17  std::optional<wasm::WasmSymbolType> Type;
18  bool IsWeak = false;
19  bool IsHidden = false;
20  bool IsComdat = false;
21  bool OmitFromLinkingSection = false;
22  mutable bool IsUsedInInitArray = false;
23  mutable bool IsUsedInGOT = false;
24  std::optional<StringRef> ImportModule;
25  std::optional<StringRef> ImportName;
26  std::optional<StringRef> ExportName;
27  wasm::WasmSignature *Signature = nullptr;
28  std::optional<wasm::WasmGlobalType> GlobalType;
29  std::optional<wasm::WasmTableType> TableType;
30
31  /// An expression describing how to calculate the size of a symbol. If a
32  /// symbol has no size this field will be NULL.
33  const MCExpr *SymbolSize = nullptr;
34
35public:
36  MCSymbolWasm(const StringMapEntry<bool> *Name, bool isTemporary)
37      : MCSymbol(SymbolKindWasm, Name, isTemporary) {}
38  static bool classof(const MCSymbol *S) { return S->isWasm(); }
39
40  const MCExpr *getSize() const { return SymbolSize; }
41  void setSize(const MCExpr *SS) { SymbolSize = SS; }
42
43  bool isFunction() const { return Type == wasm::WASM_SYMBOL_TYPE_FUNCTION; }
44  // Data is the default value if not set.
45  bool isData() const { return !Type || Type == wasm::WASM_SYMBOL_TYPE_DATA; }
46  bool isGlobal() const { return Type == wasm::WASM_SYMBOL_TYPE_GLOBAL; }
47  bool isTable() const { return Type == wasm::WASM_SYMBOL_TYPE_TABLE; }
48  bool isSection() const { return Type == wasm::WASM_SYMBOL_TYPE_SECTION; }
49  bool isTag() const { return Type == wasm::WASM_SYMBOL_TYPE_TAG; }
50
51  std::optional<wasm::WasmSymbolType> getType() const { return Type; }
52
53  void setType(wasm::WasmSymbolType type) { Type = type; }
54
55  bool isExported() const {
56    return getFlags() & wasm::WASM_SYMBOL_EXPORTED;
57  }
58  void setExported() const {
59    modifyFlags(wasm::WASM_SYMBOL_EXPORTED, wasm::WASM_SYMBOL_EXPORTED);
60  }
61
62  bool isNoStrip() const {
63    return getFlags() & wasm::WASM_SYMBOL_NO_STRIP;
64  }
65  void setNoStrip() const {
66    modifyFlags(wasm::WASM_SYMBOL_NO_STRIP, wasm::WASM_SYMBOL_NO_STRIP);
67  }
68
69  bool isTLS() const { return getFlags() & wasm::WASM_SYMBOL_TLS; }
70  void setTLS() const {
71    modifyFlags(wasm::WASM_SYMBOL_TLS, wasm::WASM_SYMBOL_TLS);
72  }
73
74  bool isWeak() const { return IsWeak; }
75  void setWeak(bool isWeak) { IsWeak = isWeak; }
76
77  bool isHidden() const { return IsHidden; }
78  void setHidden(bool isHidden) { IsHidden = isHidden; }
79
80  bool isComdat() const { return IsComdat; }
81  void setComdat(bool isComdat) { IsComdat = isComdat; }
82
83  // wasm-ld understands a finite set of symbol types.  This flag allows the
84  // compiler to avoid emitting symbol table entries that would confuse the
85  // linker, unless the user specifically requests the feature.
86  bool omitFromLinkingSection() const { return OmitFromLinkingSection; }
87  void setOmitFromLinkingSection() { OmitFromLinkingSection = true; }
88
89  bool hasImportModule() const { return ImportModule.has_value(); }
90  StringRef getImportModule() const {
91    if (ImportModule)
92      return *ImportModule;
93    // Use a default module name of "env" for now, for compatibility with
94    // existing tools.
95    // TODO(sbc): Find a way to specify a default value in the object format
96    // without picking a hardcoded value like this.
97    return "env";
98  }
99  void setImportModule(StringRef Name) { ImportModule = Name; }
100
101  bool hasImportName() const { return ImportName.has_value(); }
102  StringRef getImportName() const {
103    if (ImportName)
104      return *ImportName;
105    return getName();
106  }
107  void setImportName(StringRef Name) { ImportName = Name; }
108
109  bool hasExportName() const { return ExportName.has_value(); }
110  StringRef getExportName() const { return *ExportName; }
111  void setExportName(StringRef Name) { ExportName = Name; }
112
113  bool isFunctionTable() const {
114    return isTable() && hasTableType() &&
115           getTableType().ElemType == wasm::ValType::FUNCREF;
116  }
117  void setFunctionTable() {
118    setType(wasm::WASM_SYMBOL_TYPE_TABLE);
119    setTableType(wasm::ValType::FUNCREF);
120  }
121
122  void setUsedInGOT() const { IsUsedInGOT = true; }
123  bool isUsedInGOT() const { return IsUsedInGOT; }
124
125  void setUsedInInitArray() const { IsUsedInInitArray = true; }
126  bool isUsedInInitArray() const { return IsUsedInInitArray; }
127
128  const wasm::WasmSignature *getSignature() const { return Signature; }
129  void setSignature(wasm::WasmSignature *Sig) { Signature = Sig; }
130
131  const wasm::WasmGlobalType &getGlobalType() const {
132    assert(GlobalType);
133    return *GlobalType;
134  }
135  void setGlobalType(wasm::WasmGlobalType GT) { GlobalType = GT; }
136
137  bool hasTableType() const { return TableType.has_value(); }
138  const wasm::WasmTableType &getTableType() const {
139    assert(hasTableType());
140    return *TableType;
141  }
142  void setTableType(wasm::WasmTableType TT) { TableType = TT; }
143  void setTableType(wasm::ValType VT) {
144    // Declare a table with element type VT and no limits (min size 0, no max
145    // size).
146    wasm::WasmLimits Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
147    setTableType({VT, Limits});
148  }
149};
150
151} // end namespace llvm
152
153#endif // LLVM_MC_MCSYMBOLWASM_H
154