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/MCExpr.h" 19 #include "llvm/MC/MCObjectWriter.h" 20 #include "llvm/MC/MCSubtargetInfo.h" 21 #include "llvm/MC/MCSymbol.h" 22 #include "llvm/MC/MCValue.h" 23 #include "llvm/MC/MCWasmObjectWriter.h" 24 #include "llvm/Support/raw_ostream.h" 25 26 using namespace llvm; 27 28 namespace { 29 30 class WebAssemblyAsmBackend final : public MCAsmBackend { 31 bool Is64Bit; 32 bool IsEmscripten; 33 34 public: 35 explicit WebAssemblyAsmBackend(bool Is64Bit, bool IsEmscripten) 36 : MCAsmBackend(llvm::endianness::little), Is64Bit(Is64Bit), 37 IsEmscripten(IsEmscripten) {} 38 39 MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override; 40 41 void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target, 42 MutableArrayRef<char> Data, uint64_t Value, bool) override; 43 44 std::unique_ptr<MCObjectTargetWriter> 45 createObjectTargetWriter() const override; 46 47 bool writeNopData(raw_ostream &OS, uint64_t Count, 48 const MCSubtargetInfo *STI) const override; 49 }; 50 51 MCFixupKindInfo 52 WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { 53 const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = { 54 // This table *must* be in the order that the fixup_* kinds are defined in 55 // WebAssemblyFixupKinds.h. 56 // 57 // Name Offset (bits) Size (bits) Flags 58 {"fixup_sleb128_i32", 0, 5 * 8, 0}, 59 {"fixup_sleb128_i64", 0, 10 * 8, 0}, 60 {"fixup_uleb128_i32", 0, 5 * 8, 0}, 61 {"fixup_uleb128_i64", 0, 10 * 8, 0}, 62 }; 63 64 if (Kind < FirstTargetFixupKind) 65 return MCAsmBackend::getFixupKindInfo(Kind); 66 67 assert(unsigned(Kind - FirstTargetFixupKind) < 68 WebAssembly::NumTargetFixupKinds && 69 "Invalid kind!"); 70 return Infos[Kind - FirstTargetFixupKind]; 71 } 72 73 bool WebAssemblyAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count, 74 const MCSubtargetInfo *STI) const { 75 for (uint64_t I = 0; I < Count; ++I) 76 OS << char(WebAssembly::Nop); 77 78 return true; 79 } 80 81 void WebAssemblyAsmBackend::applyFixup(const MCFragment &F, 82 const MCFixup &Fixup, 83 const MCValue &Target, 84 MutableArrayRef<char> Data, 85 uint64_t Value, bool IsResolved) { 86 if (!IsResolved) 87 Asm->getWriter().recordRelocation(F, Fixup, Target, Value); 88 89 MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind()); 90 assert(Info.Flags == 0 && "WebAssembly does not use MCFixupKindInfo flags"); 91 92 unsigned NumBytes = alignTo(Info.TargetSize, 8) / 8; 93 if (Value == 0) 94 return; // Doesn't change encoding. 95 96 // Shift the value into position. 97 Value <<= Info.TargetOffset; 98 99 unsigned Offset = Fixup.getOffset(); 100 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!"); 101 102 // For each byte of the fragment that the fixup touches, mask in the 103 // bits from the fixup value. 104 for (unsigned I = 0; I != NumBytes; ++I) 105 Data[Offset + I] |= uint8_t((Value >> (I * 8)) & 0xff); 106 } 107 108 std::unique_ptr<MCObjectTargetWriter> 109 WebAssemblyAsmBackend::createObjectTargetWriter() const { 110 return createWebAssemblyWasmObjectWriter(Is64Bit, IsEmscripten); 111 } 112 113 } // end anonymous namespace 114 115 MCAsmBackend *llvm::createWebAssemblyAsmBackend(const Triple &TT) { 116 return new WebAssemblyAsmBackend(TT.isArch64Bit(), TT.isOSEmscripten()); 117 } 118