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