Home | History | Annotate | Download | only in MC
      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 
     36 using namespace llvm;
     37 
     38 MCWasmStreamer::~MCWasmStreamer() {}
     39 
     40 void 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   if (DF->getSubtargetInfo() == nullptr && EF->getSubtargetInfo())
     49     DF->setHasInstructions(*EF->getSubtargetInfo());
     50   DF->getContents().append(EF->getContents().begin(), EF->getContents().end());
     51 }
     52 
     53 void MCWasmStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) {
     54   // Let the target do whatever target specific stuff it needs to do.
     55   getAssembler().getBackend().handleAssemblerFlag(Flag);
     56 
     57   // Do any generic stuff we need to do.
     58   llvm_unreachable("invalid assembler flag!");
     59 }
     60 
     61 void MCWasmStreamer::ChangeSection(MCSection *Section,
     62                                    const MCExpr *Subsection) {
     63   MCAssembler &Asm = getAssembler();
     64   auto *SectionWasm = static_cast<const MCSectionWasm *>(Section);
     65   const MCSymbol *Grp = SectionWasm->getGroup();
     66   if (Grp)
     67     Asm.registerSymbol(*Grp);
     68 
     69   this->MCObjectStreamer::ChangeSection(Section, Subsection);
     70   Asm.registerSymbol(*Section->getBeginSymbol());
     71 }
     72 
     73 void MCWasmStreamer::EmitWeakReference(MCSymbol *Alias,
     74                                        const MCSymbol *Symbol) {
     75   getAssembler().registerSymbol(*Symbol);
     76   const MCExpr *Value = MCSymbolRefExpr::create(
     77       Symbol, MCSymbolRefExpr::VK_WEAKREF, getContext());
     78   Alias->setVariableValue(Value);
     79 }
     80 
     81 bool MCWasmStreamer::EmitSymbolAttribute(MCSymbol *S, MCSymbolAttr Attribute) {
     82   assert(Attribute != MCSA_IndirectSymbol && "indirect symbols not supported");
     83 
     84   auto *Symbol = cast<MCSymbolWasm>(S);
     85 
     86   // Adding a symbol attribute always introduces the symbol; note that an
     87   // important side effect of calling registerSymbol here is to register the
     88   // symbol with the assembler.
     89   getAssembler().registerSymbol(*Symbol);
     90 
     91   switch (Attribute) {
     92   case MCSA_LazyReference:
     93   case MCSA_Reference:
     94   case MCSA_SymbolResolver:
     95   case MCSA_PrivateExtern:
     96   case MCSA_WeakDefinition:
     97   case MCSA_WeakDefAutoPrivate:
     98   case MCSA_Invalid:
     99   case MCSA_IndirectSymbol:
    100   case MCSA_Protected:
    101     return false;
    102 
    103   case MCSA_Hidden:
    104     Symbol->setHidden(true);
    105     break;
    106 
    107   case MCSA_Weak:
    108   case MCSA_WeakReference:
    109     Symbol->setWeak(true);
    110     Symbol->setExternal(true);
    111     break;
    112 
    113   case MCSA_Global:
    114     Symbol->setExternal(true);
    115     break;
    116 
    117   case MCSA_ELF_TypeFunction:
    118     Symbol->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
    119     break;
    120 
    121   case MCSA_ELF_TypeObject:
    122     Symbol->setType(wasm::WASM_SYMBOL_TYPE_DATA);
    123     break;
    124 
    125   default:
    126     // unrecognized directive
    127     llvm_unreachable("unexpected MCSymbolAttr");
    128     return false;
    129   }
    130 
    131   return true;
    132 }
    133 
    134 void MCWasmStreamer::EmitCommonSymbol(MCSymbol *S, uint64_t Size,
    135                                       unsigned ByteAlignment) {
    136   llvm_unreachable("Common symbols are not yet implemented for Wasm");
    137 }
    138 
    139 void MCWasmStreamer::emitELFSize(MCSymbol *Symbol, const MCExpr *Value) {
    140   cast<MCSymbolWasm>(Symbol)->setSize(Value);
    141 }
    142 
    143 void MCWasmStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size,
    144                                            unsigned ByteAlignment) {
    145   llvm_unreachable("Local common symbols are not yet implemented for Wasm");
    146 }
    147 
    148 void MCWasmStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
    149                                    SMLoc Loc) {
    150   MCObjectStreamer::EmitValueImpl(Value, Size, Loc);
    151 }
    152 
    153 void MCWasmStreamer::EmitValueToAlignment(unsigned ByteAlignment, int64_t Value,
    154                                           unsigned ValueSize,
    155                                           unsigned MaxBytesToEmit) {
    156   MCObjectStreamer::EmitValueToAlignment(ByteAlignment, Value, ValueSize,
    157                                          MaxBytesToEmit);
    158 }
    159 
    160 void MCWasmStreamer::EmitIdent(StringRef IdentString) {
    161   // TODO(sbc): Add the ident section once we support mergable strings
    162   // sections in the object format
    163 }
    164 
    165 void MCWasmStreamer::EmitInstToFragment(const MCInst &Inst,
    166                                         const MCSubtargetInfo &STI) {
    167   this->MCObjectStreamer::EmitInstToFragment(Inst, STI);
    168 }
    169 
    170 void MCWasmStreamer::EmitInstToData(const MCInst &Inst,
    171                                     const MCSubtargetInfo &STI) {
    172   MCAssembler &Assembler = getAssembler();
    173   SmallVector<MCFixup, 4> Fixups;
    174   SmallString<256> Code;
    175   raw_svector_ostream VecOS(Code);
    176   Assembler.getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
    177 
    178   // Append the encoded instruction to the current data fragment (or create a
    179   // new such fragment if the current fragment is not a data fragment).
    180   MCDataFragment *DF = getOrCreateDataFragment();
    181 
    182   // Add the fixups and data.
    183   for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
    184     Fixups[i].setOffset(Fixups[i].getOffset() + DF->getContents().size());
    185     DF->getFixups().push_back(Fixups[i]);
    186   }
    187   DF->setHasInstructions(STI);
    188   DF->getContents().append(Code.begin(), Code.end());
    189 }
    190 
    191 void MCWasmStreamer::FinishImpl() {
    192   EmitFrames(nullptr);
    193 
    194   this->MCObjectStreamer::FinishImpl();
    195 }
    196 
    197 MCStreamer *llvm::createWasmStreamer(MCContext &Context,
    198                                      std::unique_ptr<MCAsmBackend> &&MAB,
    199                                      std::unique_ptr<MCObjectWriter> &&OW,
    200                                      std::unique_ptr<MCCodeEmitter> &&CE,
    201                                      bool RelaxAll) {
    202   MCWasmStreamer *S =
    203       new MCWasmStreamer(Context, std::move(MAB), std::move(OW), std::move(CE));
    204   if (RelaxAll)
    205     S->getAssembler().setRelaxAll(true);
    206   return S;
    207 }
    208 
    209 void MCWasmStreamer::EmitThumbFunc(MCSymbol *Func) {
    210   llvm_unreachable("Generic Wasm doesn't support this directive");
    211 }
    212 
    213 void MCWasmStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
    214   llvm_unreachable("Wasm doesn't support this directive");
    215 }
    216 
    217 void MCWasmStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
    218                                   uint64_t Size, unsigned ByteAlignment,
    219                                   SMLoc Loc) {
    220   llvm_unreachable("Wasm doesn't support this directive");
    221 }
    222 
    223 void MCWasmStreamer::EmitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
    224                                     uint64_t Size, unsigned ByteAlignment) {
    225   llvm_unreachable("Wasm doesn't support this directive");
    226 }
    227