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