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