1 | //===- lib/MC/MCWasmStreamer.cpp - Wasm Object Output ---------------------===// |
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 | // |
9 | // This file assembles .s files and emits Wasm .o object files. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "llvm/MC/MCWasmStreamer.h" |
14 | #include "llvm/ADT/SmallString.h" |
15 | #include "llvm/ADT/SmallVector.h" |
16 | #include "llvm/MC/MCAsmBackend.h" |
17 | #include "llvm/MC/MCAssembler.h" |
18 | #include "llvm/MC/MCCodeEmitter.h" |
19 | #include "llvm/MC/MCExpr.h" |
20 | #include "llvm/MC/MCFixup.h" |
21 | #include "llvm/MC/MCObjectStreamer.h" |
22 | #include "llvm/MC/MCSection.h" |
23 | #include "llvm/MC/MCSectionWasm.h" |
24 | #include "llvm/MC/MCSymbol.h" |
25 | #include "llvm/MC/MCSymbolWasm.h" |
26 | #include "llvm/MC/TargetRegistry.h" |
27 | #include "llvm/Support/Casting.h" |
28 | #include "llvm/Support/ErrorHandling.h" |
29 | |
30 | namespace llvm { |
31 | class MCContext; |
32 | class MCStreamer; |
33 | class MCSubtargetInfo; |
34 | } // namespace llvm |
35 | |
36 | using namespace llvm; |
37 | |
38 | MCWasmStreamer::~MCWasmStreamer() = default; // anchor. |
39 | |
40 | void MCWasmStreamer::emitLabel(MCSymbol *S, SMLoc Loc) { |
41 | auto *Symbol = cast<MCSymbolWasm>(Val: S); |
42 | MCObjectStreamer::emitLabel(Symbol, Loc); |
43 | |
44 | const MCSectionWasm &Section = |
45 | static_cast<const MCSectionWasm &>(*getCurrentSectionOnly()); |
46 | if (Section.getSegmentFlags() & wasm::WASM_SEG_FLAG_TLS) |
47 | Symbol->setTLS(); |
48 | } |
49 | |
50 | void MCWasmStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCDataFragment &F, |
51 | uint64_t Offset) { |
52 | auto *Symbol = cast<MCSymbolWasm>(Val: S); |
53 | MCObjectStreamer::emitLabelAtPos(Symbol, Loc, F, Offset); |
54 | |
55 | const MCSectionWasm &Section = |
56 | static_cast<const MCSectionWasm &>(*getCurrentSectionOnly()); |
57 | if (Section.getSegmentFlags() & wasm::WASM_SEG_FLAG_TLS) |
58 | Symbol->setTLS(); |
59 | } |
60 | |
61 | void MCWasmStreamer::changeSection(MCSection *Section, uint32_t Subsection) { |
62 | MCAssembler &Asm = getAssembler(); |
63 | auto *SectionWasm = cast<MCSectionWasm>(Val: Section); |
64 | const MCSymbol *Grp = SectionWasm->getGroup(); |
65 | if (Grp) |
66 | Asm.registerSymbol(Symbol: *Grp); |
67 | |
68 | this->MCObjectStreamer::changeSection(Section, Subsection); |
69 | Asm.registerSymbol(Symbol: *Section->getBeginSymbol()); |
70 | } |
71 | |
72 | bool MCWasmStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) { |
73 | assert(Attribute != MCSA_IndirectSymbol && "indirect symbols not supported" ); |
74 | |
75 | auto *Symbol = cast<MCSymbolWasm>(Val: S); |
76 | |
77 | // Adding a symbol attribute always introduces the symbol; note that an |
78 | // important side effect of calling registerSymbol here is to register the |
79 | // symbol with the assembler. |
80 | getAssembler().registerSymbol(Symbol: *Symbol); |
81 | |
82 | switch (Attribute) { |
83 | case MCSA_LazyReference: |
84 | case MCSA_Reference: |
85 | case MCSA_SymbolResolver: |
86 | case MCSA_PrivateExtern: |
87 | case MCSA_WeakDefinition: |
88 | case MCSA_WeakDefAutoPrivate: |
89 | case MCSA_Invalid: |
90 | case MCSA_IndirectSymbol: |
91 | case MCSA_Protected: |
92 | case MCSA_Exported: |
93 | return false; |
94 | |
95 | case MCSA_Hidden: |
96 | Symbol->setHidden(true); |
97 | break; |
98 | |
99 | case MCSA_Weak: |
100 | case MCSA_WeakReference: |
101 | Symbol->setWeak(true); |
102 | Symbol->setExternal(true); |
103 | break; |
104 | |
105 | case MCSA_Global: |
106 | Symbol->setExternal(true); |
107 | break; |
108 | |
109 | case MCSA_ELF_TypeFunction: |
110 | Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION); |
111 | break; |
112 | |
113 | case MCSA_ELF_TypeTLS: |
114 | Symbol->setTLS(); |
115 | break; |
116 | |
117 | case MCSA_ELF_TypeObject: |
118 | case MCSA_Cold: |
119 | break; |
120 | |
121 | case MCSA_NoDeadStrip: |
122 | Symbol->setNoStrip(); |
123 | break; |
124 | |
125 | default: |
126 | // unrecognized directive |
127 | llvm_unreachable("unexpected MCSymbolAttr" ); |
128 | return false; |
129 | } |
130 | |
131 | return true; |
132 | } |
133 | |
134 | void MCWasmStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size, |
135 | Align ByteAlignment) { |
136 | llvm_unreachable("Common symbols are not yet implemented for Wasm" ); |
137 | } |
138 | |
139 | void MCWasmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) { |
140 | cast<MCSymbolWasm>(Val: Symbol)->setSize(Value); |
141 | } |
142 | |
143 | void MCWasmStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size, |
144 | Align ByteAlignment) { |
145 | llvm_unreachable("Local common symbols are not yet implemented for Wasm" ); |
146 | } |
147 | |
148 | void MCWasmStreamer::emitIdent(StringRef IdentString) { |
149 | // TODO(sbc): Add the ident section once we support mergable strings |
150 | // sections in the object format |
151 | } |
152 | |
153 | void MCWasmStreamer::finishImpl() { |
154 | emitFrames(MAB: nullptr); |
155 | |
156 | this->MCObjectStreamer::finishImpl(); |
157 | } |
158 | |
159 | MCStreamer *llvm::createWasmStreamer(MCContext &Context, |
160 | std::unique_ptr<MCAsmBackend> &&MAB, |
161 | std::unique_ptr<MCObjectWriter> &&OW, |
162 | std::unique_ptr<MCCodeEmitter> &&CE) { |
163 | MCWasmStreamer *S = |
164 | new MCWasmStreamer(Context, std::move(MAB), std::move(OW), std::move(CE)); |
165 | return S; |
166 | } |
167 | |