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