xref: /freebsd/contrib/llvm-project/llvm/lib/MC/MCWasmStreamer.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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