xref: /openbsd-src/gnu/llvm/llvm/lib/MC/MCWasmStreamer.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- lib/MC/MCWasmStreamer.cpp - Wasm Object Output ---------------------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This file assembles .s files and emits Wasm .o object files.
1009467b48Spatrick //
1109467b48Spatrick //===----------------------------------------------------------------------===//
1209467b48Spatrick 
1309467b48Spatrick #include "llvm/MC/MCWasmStreamer.h"
14*d415bd75Srobert #include "llvm/ADT/SmallString.h"
15*d415bd75Srobert #include "llvm/ADT/SmallVector.h"
1609467b48Spatrick #include "llvm/MC/MCAsmBackend.h"
1709467b48Spatrick #include "llvm/MC/MCAssembler.h"
1809467b48Spatrick #include "llvm/MC/MCCodeEmitter.h"
1909467b48Spatrick #include "llvm/MC/MCExpr.h"
20*d415bd75Srobert #include "llvm/MC/MCFixup.h"
21*d415bd75Srobert #include "llvm/MC/MCFragment.h"
2209467b48Spatrick #include "llvm/MC/MCObjectStreamer.h"
2309467b48Spatrick #include "llvm/MC/MCSection.h"
2409467b48Spatrick #include "llvm/MC/MCSectionWasm.h"
2509467b48Spatrick #include "llvm/MC/MCSymbol.h"
2609467b48Spatrick #include "llvm/MC/MCSymbolWasm.h"
27*d415bd75Srobert #include "llvm/MC/TargetRegistry.h"
2809467b48Spatrick #include "llvm/Support/Casting.h"
2909467b48Spatrick #include "llvm/Support/ErrorHandling.h"
3009467b48Spatrick #include "llvm/Support/raw_ostream.h"
3109467b48Spatrick 
32*d415bd75Srobert namespace llvm {
33*d415bd75Srobert class MCContext;
34*d415bd75Srobert class MCStreamer;
35*d415bd75Srobert class MCSubtargetInfo;
36*d415bd75Srobert } // namespace llvm
37*d415bd75Srobert 
3809467b48Spatrick using namespace llvm;
3909467b48Spatrick 
4009467b48Spatrick MCWasmStreamer::~MCWasmStreamer() = default; // anchor.
4109467b48Spatrick 
mergeFragment(MCDataFragment * DF,MCDataFragment * EF)4209467b48Spatrick void MCWasmStreamer::mergeFragment(MCDataFragment *DF, MCDataFragment *EF) {
4309467b48Spatrick   flushPendingLabels(DF, DF->getContents().size());
4409467b48Spatrick 
4509467b48Spatrick   for (unsigned I = 0, E = EF->getFixups().size(); I != E; ++I) {
4609467b48Spatrick     EF->getFixups()[I].setOffset(EF->getFixups()[I].getOffset() +
4709467b48Spatrick                                  DF->getContents().size());
4809467b48Spatrick     DF->getFixups().push_back(EF->getFixups()[I]);
4909467b48Spatrick   }
5009467b48Spatrick   if (DF->getSubtargetInfo() == nullptr && EF->getSubtargetInfo())
5109467b48Spatrick     DF->setHasInstructions(*EF->getSubtargetInfo());
5209467b48Spatrick   DF->getContents().append(EF->getContents().begin(), EF->getContents().end());
5309467b48Spatrick }
5409467b48Spatrick 
emitLabel(MCSymbol * S,SMLoc Loc)55*d415bd75Srobert void MCWasmStreamer::emitLabel(MCSymbol *S, SMLoc Loc) {
56*d415bd75Srobert   auto *Symbol = cast<MCSymbolWasm>(S);
57*d415bd75Srobert   MCObjectStreamer::emitLabel(Symbol, Loc);
58*d415bd75Srobert 
59*d415bd75Srobert   const MCSectionWasm &Section =
60*d415bd75Srobert       static_cast<const MCSectionWasm &>(*getCurrentSectionOnly());
61*d415bd75Srobert   if (Section.getSegmentFlags() & wasm::WASM_SEG_FLAG_TLS)
62*d415bd75Srobert     Symbol->setTLS();
63*d415bd75Srobert }
64*d415bd75Srobert 
emitLabelAtPos(MCSymbol * S,SMLoc Loc,MCFragment * F,uint64_t Offset)65*d415bd75Srobert void MCWasmStreamer::emitLabelAtPos(MCSymbol *S, SMLoc Loc, MCFragment *F,
66*d415bd75Srobert                                     uint64_t Offset) {
67*d415bd75Srobert   auto *Symbol = cast<MCSymbolWasm>(S);
68*d415bd75Srobert   MCObjectStreamer::emitLabelAtPos(Symbol, Loc, F, Offset);
69*d415bd75Srobert 
70*d415bd75Srobert   const MCSectionWasm &Section =
71*d415bd75Srobert       static_cast<const MCSectionWasm &>(*getCurrentSectionOnly());
72*d415bd75Srobert   if (Section.getSegmentFlags() & wasm::WASM_SEG_FLAG_TLS)
73*d415bd75Srobert     Symbol->setTLS();
74*d415bd75Srobert }
75*d415bd75Srobert 
emitAssemblerFlag(MCAssemblerFlag Flag)76097a140dSpatrick void MCWasmStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
7709467b48Spatrick   // Let the target do whatever target specific stuff it needs to do.
7809467b48Spatrick   getAssembler().getBackend().handleAssemblerFlag(Flag);
7909467b48Spatrick 
8009467b48Spatrick   // Do any generic stuff we need to do.
8109467b48Spatrick   llvm_unreachable("invalid assembler flag!");
8209467b48Spatrick }
8309467b48Spatrick 
changeSection(MCSection * Section,const MCExpr * Subsection)84097a140dSpatrick void MCWasmStreamer::changeSection(MCSection *Section,
8509467b48Spatrick                                    const MCExpr *Subsection) {
8609467b48Spatrick   MCAssembler &Asm = getAssembler();
8709467b48Spatrick   auto *SectionWasm = cast<MCSectionWasm>(Section);
8809467b48Spatrick   const MCSymbol *Grp = SectionWasm->getGroup();
8909467b48Spatrick   if (Grp)
9009467b48Spatrick     Asm.registerSymbol(*Grp);
9109467b48Spatrick 
92097a140dSpatrick   this->MCObjectStreamer::changeSection(Section, Subsection);
9309467b48Spatrick   Asm.registerSymbol(*Section->getBeginSymbol());
9409467b48Spatrick }
9509467b48Spatrick 
emitWeakReference(MCSymbol * Alias,const MCSymbol * Symbol)96097a140dSpatrick void MCWasmStreamer::emitWeakReference(MCSymbol *Alias,
9709467b48Spatrick                                        const MCSymbol *Symbol) {
9809467b48Spatrick   getAssembler().registerSymbol(*Symbol);
9909467b48Spatrick   const MCExpr *Value = MCSymbolRefExpr::create(
10009467b48Spatrick       Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext());
10109467b48Spatrick   Alias->setVariableValue(Value);
10209467b48Spatrick }
10309467b48Spatrick 
emitSymbolAttribute(MCSymbol * S,MCSymbolAttr Attribute)104097a140dSpatrick bool MCWasmStreamer::emitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
10509467b48Spatrick   assert(Attribute != MCSA_IndirectSymbol && "indirect symbols not supported");
10609467b48Spatrick 
10709467b48Spatrick   auto *Symbol = cast<MCSymbolWasm>(S);
10809467b48Spatrick 
10909467b48Spatrick   // Adding a symbol attribute always introduces the symbol; note that an
11009467b48Spatrick   // important side effect of calling registerSymbol here is to register the
11109467b48Spatrick   // symbol with the assembler.
11209467b48Spatrick   getAssembler().registerSymbol(*Symbol);
11309467b48Spatrick 
11409467b48Spatrick   switch (Attribute) {
11509467b48Spatrick   case MCSA_LazyReference:
11609467b48Spatrick   case MCSA_Reference:
11709467b48Spatrick   case MCSA_SymbolResolver:
11809467b48Spatrick   case MCSA_PrivateExtern:
11909467b48Spatrick   case MCSA_WeakDefinition:
12009467b48Spatrick   case MCSA_WeakDefAutoPrivate:
12109467b48Spatrick   case MCSA_Invalid:
12209467b48Spatrick   case MCSA_IndirectSymbol:
12309467b48Spatrick   case MCSA_Protected:
124*d415bd75Srobert   case MCSA_Exported:
12509467b48Spatrick     return false;
12609467b48Spatrick 
12709467b48Spatrick   case MCSA_Hidden:
12809467b48Spatrick     Symbol->setHidden(true);
12909467b48Spatrick     break;
13009467b48Spatrick 
13109467b48Spatrick   case MCSA_Weak:
13209467b48Spatrick   case MCSA_WeakReference:
13309467b48Spatrick     Symbol->setWeak(true);
13409467b48Spatrick     Symbol->setExternal(true);
13509467b48Spatrick     break;
13609467b48Spatrick 
13709467b48Spatrick   case MCSA_Global:
13809467b48Spatrick     Symbol->setExternal(true);
13909467b48Spatrick     break;
14009467b48Spatrick 
14109467b48Spatrick   case MCSA_ELF_TypeFunction:
14209467b48Spatrick     Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
14309467b48Spatrick     break;
14409467b48Spatrick 
145*d415bd75Srobert   case MCSA_ELF_TypeTLS:
146*d415bd75Srobert     Symbol->setTLS();
147*d415bd75Srobert     break;
148*d415bd75Srobert 
14909467b48Spatrick   case MCSA_ELF_TypeObject:
15009467b48Spatrick   case MCSA_Cold:
15109467b48Spatrick     break;
15209467b48Spatrick 
15309467b48Spatrick   case MCSA_NoDeadStrip:
15409467b48Spatrick     Symbol->setNoStrip();
15509467b48Spatrick     break;
15609467b48Spatrick 
15709467b48Spatrick   default:
15809467b48Spatrick     // unrecognized directive
15909467b48Spatrick     llvm_unreachable("unexpected MCSymbolAttr");
16009467b48Spatrick     return false;
16109467b48Spatrick   }
16209467b48Spatrick 
16309467b48Spatrick   return true;
16409467b48Spatrick }
16509467b48Spatrick 
emitCommonSymbol(MCSymbol * S,uint64_t Size,Align ByteAlignment)166097a140dSpatrick void MCWasmStreamer::emitCommonSymbol(MCSymbol *S, uint64_t Size,
167*d415bd75Srobert                                       Align ByteAlignment) {
16809467b48Spatrick   llvm_unreachable("Common symbols are not yet implemented for Wasm");
16909467b48Spatrick }
17009467b48Spatrick 
emitELFSize(MCSymbol * Symbol,const MCExpr * Value)17109467b48Spatrick void MCWasmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
17209467b48Spatrick   cast<MCSymbolWasm>(Symbol)->setSize(Value);
17309467b48Spatrick }
17409467b48Spatrick 
emitLocalCommonSymbol(MCSymbol * S,uint64_t Size,Align ByteAlignment)175097a140dSpatrick void MCWasmStreamer::emitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
176*d415bd75Srobert                                            Align ByteAlignment) {
17709467b48Spatrick   llvm_unreachable("Local common symbols are not yet implemented for Wasm");
17809467b48Spatrick }
17909467b48Spatrick 
emitIdent(StringRef IdentString)180097a140dSpatrick void MCWasmStreamer::emitIdent(StringRef IdentString) {
18109467b48Spatrick   // TODO(sbc): Add the ident section once we support mergable strings
18209467b48Spatrick   // sections in the object format
18309467b48Spatrick }
18409467b48Spatrick 
emitInstToFragment(const MCInst & Inst,const MCSubtargetInfo & STI)185097a140dSpatrick void MCWasmStreamer::emitInstToFragment(const MCInst &Inst,
18609467b48Spatrick                                         const MCSubtargetInfo &STI) {
187097a140dSpatrick   this->MCObjectStreamer::emitInstToFragment(Inst, STI);
188*d415bd75Srobert   MCRelaxableFragment &F = *cast<MCRelaxableFragment>(getCurrentFragment());
189*d415bd75Srobert 
190*d415bd75Srobert   for (auto &Fixup : F.getFixups())
191*d415bd75Srobert     fixSymbolsInTLSFixups(Fixup.getValue());
19209467b48Spatrick }
19309467b48Spatrick 
emitInstToData(const MCInst & Inst,const MCSubtargetInfo & STI)194097a140dSpatrick void MCWasmStreamer::emitInstToData(const MCInst &Inst,
19509467b48Spatrick                                     const MCSubtargetInfo &STI) {
19609467b48Spatrick   MCAssembler &Assembler = getAssembler();
19709467b48Spatrick   SmallVector<MCFixup, 4> Fixups;
19809467b48Spatrick   SmallString<256> Code;
19909467b48Spatrick   raw_svector_ostream VecOS(Code);
20009467b48Spatrick   Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
20109467b48Spatrick 
202*d415bd75Srobert   for (auto &Fixup : Fixups)
203*d415bd75Srobert     fixSymbolsInTLSFixups(Fixup.getValue());
204*d415bd75Srobert 
20509467b48Spatrick   // Append the encoded instruction to the current data fragment (or create a
20609467b48Spatrick   // new such fragment if the current fragment is not a data fragment).
20709467b48Spatrick   MCDataFragment *DF = getOrCreateDataFragment();
20809467b48Spatrick 
20909467b48Spatrick   // Add the fixups and data.
21009467b48Spatrick   for (unsigned I = 0, E = Fixups.size(); I != E; ++I) {
21109467b48Spatrick     Fixups[I].setOffset(Fixups[I].getOffset() + DF->getContents().size());
21209467b48Spatrick     DF->getFixups().push_back(Fixups[I]);
21309467b48Spatrick   }
21409467b48Spatrick   DF->setHasInstructions(STI);
21509467b48Spatrick   DF->getContents().append(Code.begin(), Code.end());
21609467b48Spatrick }
21709467b48Spatrick 
finishImpl()218097a140dSpatrick void MCWasmStreamer::finishImpl() {
219097a140dSpatrick   emitFrames(nullptr);
22009467b48Spatrick 
221097a140dSpatrick   this->MCObjectStreamer::finishImpl();
22209467b48Spatrick }
22309467b48Spatrick 
fixSymbolsInTLSFixups(const MCExpr * expr)224*d415bd75Srobert void MCWasmStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
225*d415bd75Srobert   switch (expr->getKind()) {
226*d415bd75Srobert   case MCExpr::Target:
227*d415bd75Srobert   case MCExpr::Constant:
228*d415bd75Srobert     break;
229*d415bd75Srobert 
230*d415bd75Srobert   case MCExpr::Binary: {
231*d415bd75Srobert     const MCBinaryExpr *be = cast<MCBinaryExpr>(expr);
232*d415bd75Srobert     fixSymbolsInTLSFixups(be->getLHS());
233*d415bd75Srobert     fixSymbolsInTLSFixups(be->getRHS());
234*d415bd75Srobert     break;
235*d415bd75Srobert   }
236*d415bd75Srobert 
237*d415bd75Srobert   case MCExpr::SymbolRef: {
238*d415bd75Srobert     const MCSymbolRefExpr &symRef = *cast<MCSymbolRefExpr>(expr);
239*d415bd75Srobert     switch (symRef.getKind()) {
240*d415bd75Srobert     case MCSymbolRefExpr::VK_WASM_TLSREL:
241*d415bd75Srobert     case MCSymbolRefExpr::VK_WASM_GOT_TLS:
242*d415bd75Srobert       getAssembler().registerSymbol(symRef.getSymbol());
243*d415bd75Srobert       cast<MCSymbolWasm>(symRef.getSymbol()).setTLS();
244*d415bd75Srobert       break;
245*d415bd75Srobert     default:
246*d415bd75Srobert       break;
247*d415bd75Srobert     }
248*d415bd75Srobert     break;
249*d415bd75Srobert   }
250*d415bd75Srobert 
251*d415bd75Srobert   case MCExpr::Unary:
252*d415bd75Srobert     fixSymbolsInTLSFixups(cast<MCUnaryExpr>(expr)->getSubExpr());
253*d415bd75Srobert     break;
254*d415bd75Srobert   }
25509467b48Spatrick }
25609467b48Spatrick 
emitThumbFunc(MCSymbol * Func)257097a140dSpatrick void MCWasmStreamer::emitThumbFunc(MCSymbol *Func) {
25809467b48Spatrick   llvm_unreachable("Generic Wasm doesn't support this directive");
25909467b48Spatrick }
26009467b48Spatrick 
emitSymbolDesc(MCSymbol * Symbol,unsigned DescValue)261097a140dSpatrick void MCWasmStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
26209467b48Spatrick   llvm_unreachable("Wasm doesn't support this directive");
26309467b48Spatrick }
26409467b48Spatrick 
emitZerofill(MCSection * Section,MCSymbol * Symbol,uint64_t Size,Align ByteAlignment,SMLoc Loc)265097a140dSpatrick void MCWasmStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
266*d415bd75Srobert                                   uint64_t Size, Align ByteAlignment,
26709467b48Spatrick                                   SMLoc Loc) {
26809467b48Spatrick   llvm_unreachable("Wasm doesn't support this directive");
26909467b48Spatrick }
27009467b48Spatrick 
emitTBSSSymbol(MCSection * Section,MCSymbol * Symbol,uint64_t Size,Align ByteAlignment)271097a140dSpatrick void MCWasmStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
272*d415bd75Srobert                                     uint64_t Size, Align ByteAlignment) {
27309467b48Spatrick   llvm_unreachable("Wasm doesn't support this directive");
27409467b48Spatrick }
275*d415bd75Srobert 
createWasmStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> && MAB,std::unique_ptr<MCObjectWriter> && OW,std::unique_ptr<MCCodeEmitter> && CE,bool RelaxAll)276*d415bd75Srobert MCStreamer *llvm::createWasmStreamer(MCContext &Context,
277*d415bd75Srobert                                      std::unique_ptr<MCAsmBackend> &&MAB,
278*d415bd75Srobert                                      std::unique_ptr<MCObjectWriter> &&OW,
279*d415bd75Srobert                                      std::unique_ptr<MCCodeEmitter> &&CE,
280*d415bd75Srobert                                      bool RelaxAll) {
281*d415bd75Srobert   MCWasmStreamer *S =
282*d415bd75Srobert       new MCWasmStreamer(Context, std::move(MAB), std::move(OW), std::move(CE));
283*d415bd75Srobert   if (RelaxAll)
284*d415bd75Srobert     S->getAssembler().setRelaxAll(true);
285*d415bd75Srobert   return S;
286*d415bd75Srobert }
287