MCWasmStreamer.cpp revision 327952
1//===- lib/MC/MCWasmStreamer.cpp - Wasm Object Output ---------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file assembles .s files and emits Wasm .o object files.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/MC/MCWasmStreamer.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/SmallPtrSet.h"
17#include "llvm/MC/MCAsmBackend.h"
18#include "llvm/MC/MCAsmLayout.h"
19#include "llvm/MC/MCAssembler.h"
20#include "llvm/MC/MCCodeEmitter.h"
21#include "llvm/MC/MCContext.h"
22#include "llvm/MC/MCExpr.h"
23#include "llvm/MC/MCInst.h"
24#include "llvm/MC/MCObjectStreamer.h"
25#include "llvm/MC/MCSection.h"
26#include "llvm/MC/MCSectionWasm.h"
27#include "llvm/MC/MCSymbol.h"
28#include "llvm/MC/MCSymbolWasm.h"
29#include "llvm/MC/MCValue.h"
30#include "llvm/Support/Casting.h"
31#include "llvm/Support/Debug.h"
32#include "llvm/Support/ErrorHandling.h"
33#include "llvm/Support/TargetRegistry.h"
34#include "llvm/Support/raw_ostream.h"
35
36using namespace llvm;
37
38MCWasmStreamer::~MCWasmStreamer() {}
39
40void MCWasmStreamer::mergeFragment(MCDataFragment *DF, MCDataFragment *EF) {
41  flushPendingLabels(DF, DF->getContents().size());
42
43  for (unsigned i = 0, e = EF->getFixups().size(); i != e; ++i) {
44    EF->getFixups()[i].setOffset(EF->getFixups()[i].getOffset() +
45                                 DF->getContents().size());
46    DF->getFixups().push_back(EF->getFixups()[i]);
47  }
48  DF->setHasInstructions(true);
49  DF->getContents().append(EF->getContents().begin(), EF->getContents().end());
50}
51
52void MCWasmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
53  // Let the target do whatever target specific stuff it needs to do.
54  getAssembler().getBackend().handleAssemblerFlag(Flag);
55
56  // Do any generic stuff we need to do.
57  llvm_unreachable("invalid assembler flag!");
58}
59
60void MCWasmStreamer::ChangeSection(MCSection *Section,
61                                   const MCExpr *Subsection) {
62  MCAssembler &Asm = getAssembler();
63  auto *SectionWasm = static_cast<const MCSectionWasm *>(Section);
64  const MCSymbol *Grp = SectionWasm->getGroup();
65  if (Grp)
66    Asm.registerSymbol(*Grp);
67
68  this->MCObjectStreamer::ChangeSection(Section, Subsection);
69}
70
71void MCWasmStreamer::EmitWeakReference(MCSymbol *Alias,
72                                       const MCSymbol *Symbol) {
73  getAssembler().registerSymbol(*Symbol);
74  const MCExpr *Value = MCSymbolRefExpr::create(
75      Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext());
76  Alias->setVariableValue(Value);
77}
78
79bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
80  assert(Attribute != MCSA_IndirectSymbol && "indirect symbols not supported");
81
82  auto *Symbol = cast<MCSymbolWasm>(S);
83
84  // Adding a symbol attribute always introduces the symbol, note that an
85  // important side effect of calling registerSymbol here is to register
86  // the symbol with the assembler.
87  getAssembler().registerSymbol(*Symbol);
88
89  switch (Attribute) {
90  case MCSA_LazyReference:
91  case MCSA_Reference:
92  case MCSA_SymbolResolver:
93  case MCSA_PrivateExtern:
94  case MCSA_WeakDefinition:
95  case MCSA_WeakDefAutoPrivate:
96  case MCSA_Invalid:
97  case MCSA_IndirectSymbol:
98  case MCSA_Protected:
99    return false;
100
101  case MCSA_Hidden:
102    Symbol->setHidden(true);
103    break;
104
105  case MCSA_Weak:
106  case MCSA_WeakReference:
107    Symbol->setWeak(true);
108    Symbol->setExternal(true);
109    break;
110
111  case MCSA_Global:
112    Symbol->setExternal(true);
113    break;
114
115  case MCSA_ELF_TypeFunction:
116    Symbol->setIsFunction(true);
117    break;
118
119  case MCSA_ELF_TypeObject:
120    Symbol->setIsFunction(false);
121    break;
122
123  default:
124    // unrecognized directive
125    llvm_unreachable("unexpected MCSymbolAttr");
126    return false;
127  }
128
129  return true;
130}
131
132void MCWasmStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
133                                      unsigned ByteAlignment) {
134  llvm_unreachable("Common symbols are not yet implemented for Wasm");
135}
136
137void MCWasmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
138  cast<MCSymbolWasm>(Symbol)->setSize(Value);
139}
140
141void MCWasmStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
142                                           unsigned ByteAlignment) {
143  llvm_unreachable("Local common symbols are not yet implemented for Wasm");
144}
145
146void MCWasmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
147                                   SMLoc Loc) {
148  MCObjectStreamer::EmitValueImpl(Value, Size, Loc);
149}
150
151void MCWasmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
152                                          unsigned ValueSize,
153                                          unsigned MaxBytesToEmit) {
154  MCObjectStreamer::EmitValueToAlignment(ByteAlignment, Value, ValueSize,
155                                         MaxBytesToEmit);
156}
157
158void MCWasmStreamer::EmitIdent(StringRef IdentString) {
159  MCSection *Comment = getAssembler().getContext().getWasmSection(
160      ".comment", SectionKind::getMetadata());
161  PushSection();
162  SwitchSection(Comment);
163  if (!SeenIdent) {
164    EmitIntValue(0, 1);
165    SeenIdent = true;
166  }
167  EmitBytes(IdentString);
168  EmitIntValue(0, 1);
169  PopSection();
170}
171
172void MCWasmStreamer::EmitInstToFragment(const MCInst &Inst,
173                                        const MCSubtargetInfo &STI) {
174  this->MCObjectStreamer::EmitInstToFragment(Inst, STI);
175}
176
177void MCWasmStreamer::EmitInstToData(const MCInst &Inst,
178                                    const MCSubtargetInfo &STI) {
179  MCAssembler &Assembler = getAssembler();
180  SmallVector<MCFixup, 4> Fixups;
181  SmallString<256> Code;
182  raw_svector_ostream VecOS(Code);
183  Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
184
185  // Append the encoded instruction to the current data fragment (or create a
186  // new such fragment if the current fragment is not a data fragment).
187  MCDataFragment *DF = getOrCreateDataFragment();
188
189  // Add the fixups and data.
190  for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
191    Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
192    DF->getFixups().push_back(Fixups[i]);
193  }
194  DF->setHasInstructions(true);
195  DF->getContents().append(Code.begin(), Code.end());
196}
197
198void MCWasmStreamer::FinishImpl() {
199  EmitFrames(nullptr);
200
201  this->MCObjectStreamer::FinishImpl();
202}
203
204MCStreamer *llvm::createWasmStreamer(MCContext &Context,
205                                     std::unique_ptr<MCAsmBackend> &&MAB,
206                                     raw_pwrite_stream &OS,
207                                     std::unique_ptr<MCCodeEmitter> &&CE,
208                                     bool RelaxAll) {
209  MCWasmStreamer *S =
210      new MCWasmStreamer(Context, std::move(MAB), OS, std::move(CE));
211  if (RelaxAll)
212    S->getAssembler().setRelaxAll(true);
213  return S;
214}
215
216void MCWasmStreamer::EmitThumbFunc(MCSymbol *Func) {
217  llvm_unreachable("Generic Wasm doesn't support this directive");
218}
219
220void MCWasmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
221  llvm_unreachable("Wasm doesn't support this directive");
222}
223
224void MCWasmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
225                                  uint64_t Size, unsigned ByteAlignment) {
226  llvm_unreachable("Wasm doesn't support this directive");
227}
228
229void MCWasmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
230                                    uint64_t Size, unsigned ByteAlignment) {
231  llvm_unreachable("Wasm doesn't support this directive");
232}
233