1 //===-- WebAssemblyAsmBackend.cpp - WebAssembly Assembler Backend ---------===// 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 /// \file 11 /// This file implements the WebAssemblyAsmBackend class. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "MCTargetDesc/WebAssemblyFixupKinds.h" 16 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 17 #include "llvm/MC/MCAsmBackend.h" 18 #include "llvm/MC/MCAssembler.h" 19 #include "llvm/MC/MCDirectives.h" 20 #include "llvm/MC/MCELFObjectWriter.h" 21 #include "llvm/MC/MCExpr.h" 22 #include "llvm/MC/MCFixupKindInfo.h" 23 #include "llvm/MC/MCObjectWriter.h" 24 #include "llvm/MC/MCSubtargetInfo.h" 25 #include "llvm/MC/MCSymbol.h" 26 #include "llvm/MC/MCWasmObjectWriter.h" 27 #include "llvm/Support/ErrorHandling.h" 28 #include "llvm/Support/raw_ostream.h" 29 using namespace llvm; 30 31 namespace { 32 33 class WebAssemblyAsmBackend final : public MCAsmBackend { 34 bool Is64Bit; 35 bool IsELF; 36 37 public: 38 explicit WebAssemblyAsmBackend(bool Is64Bit, bool IsELF) 39 : MCAsmBackend(support::little), Is64Bit(Is64Bit), IsELF(IsELF) {} 40 ~WebAssemblyAsmBackend() override {} 41 42 unsigned getNumFixupKinds() const override { 43 return WebAssembly::NumTargetFixupKinds; 44 } 45 46 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; 47 48 void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, 49 const MCValue &Target, MutableArrayRef<char> Data, 50 uint64_t Value, bool IsPCRel, 51 const MCSubtargetInfo *STI) const override; 52 53 std::unique_ptr<MCObjectTargetWriter> 54 createObjectTargetWriter() const override; 55 56 // No instruction requires relaxation 57 bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, 58 const MCRelaxableFragment *DF, 59 const MCAsmLayout &Layout) const override { 60 return false; 61 } 62 63 bool mayNeedRelaxation(const MCInst &Inst, 64 const MCSubtargetInfo &STI) const override { 65 return false; 66 } 67 68 void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, 69 MCInst &Res) const override {} 70 71 bool writeNopData(raw_ostream &OS, uint64_t Count) const override; 72 }; 73 74 const MCFixupKindInfo & 75 WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { 76 const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = { 77 // This table *must* be in the order that the fixup_* kinds are defined in 78 // WebAssemblyFixupKinds.h. 79 // 80 // Name Offset (bits) Size (bits) Flags 81 { "fixup_code_sleb128_i32", 0, 5*8, 0 }, 82 { "fixup_code_sleb128_i64", 0, 10*8, 0 }, 83 { "fixup_code_uleb128_i32", 0, 5*8, 0 }, 84 }; 85 86 if (Kind < FirstTargetFixupKind) 87 return MCAsmBackend::getFixupKindInfo(Kind); 88 89 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 90 "Invalid kind!"); 91 return Infos[Kind - FirstTargetFixupKind]; 92 } 93 94 bool WebAssemblyAsmBackend::writeNopData(raw_ostream &OS, 95 uint64_t Count) const { 96 for (uint64_t i = 0; i < Count; ++i) 97 OS << char(WebAssembly::Nop); 98 99 return true; 100 } 101 102 void WebAssemblyAsmBackend::applyFixup(const MCAssembler &Asm, 103 const MCFixup &Fixup, 104 const MCValue &Target, 105 MutableArrayRef<char> Data, 106 uint64_t Value, bool IsPCRel, 107 const MCSubtargetInfo *STI) const { 108 const MCFixupKindInfo &Info = getFixupKindInfo(Fixup.getKind()); 109 assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags"); 110 111 unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8; 112 if (Value == 0) 113 return; // Doesn't change encoding. 114 115 // Shift the value into position. 116 Value <<= Info.TargetOffset; 117 118 unsigned Offset = Fixup.getOffset(); 119 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!"); 120 121 // For each byte of the fragment that the fixup touches, mask in the 122 // bits from the fixup value. 123 for (unsigned i = 0; i != NumBytes; ++i) 124 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff); 125 } 126 127 std::unique_ptr<MCObjectTargetWriter> 128 WebAssemblyAsmBackend::createObjectTargetWriter() const { 129 return IsELF ? createWebAssemblyELFObjectWriter(Is64Bit, 0) 130 : createWebAssemblyWasmObjectWriter(Is64Bit); 131 } 132 133 } // end anonymous namespace 134 135 MCAsmBackend *llvm::createWebAssemblyAsmBackend(const Triple &TT) { 136 return new WebAssemblyAsmBackend(TT.isArch64Bit(), TT.isOSBinFormatELF()); 137 } 138