136 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file implements the WebAssemblyAsmBackend class.11///12//===----------------------------------------------------------------------===//13 14#include "MCTargetDesc/WebAssemblyFixupKinds.h"15#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"16#include "llvm/ADT/StringSwitch.h"17#include "llvm/MC/MCAsmBackend.h"18#include "llvm/MC/MCAssembler.h"19#include "llvm/MC/MCExpr.h"20#include "llvm/MC/MCObjectWriter.h"21#include "llvm/MC/MCSubtargetInfo.h"22#include "llvm/MC/MCSymbol.h"23#include "llvm/MC/MCValue.h"24#include "llvm/MC/MCWasmObjectWriter.h"25#include "llvm/Support/raw_ostream.h"26 27using namespace llvm;28 29namespace {30 31class WebAssemblyAsmBackend final : public MCAsmBackend {32 bool Is64Bit;33 bool IsEmscripten;34 35public:36 explicit WebAssemblyAsmBackend(bool Is64Bit, bool IsEmscripten)37 : MCAsmBackend(llvm::endianness::little), Is64Bit(Is64Bit),38 IsEmscripten(IsEmscripten) {}39 40 std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;41 MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;42 43 void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,44 uint8_t *Data, uint64_t Value, bool) override;45 46 std::unique_ptr<MCObjectTargetWriter>47 createObjectTargetWriter() const override;48 49 bool writeNopData(raw_ostream &OS, uint64_t Count,50 const MCSubtargetInfo *STI) const override;51};52 53std::optional<MCFixupKind>54WebAssemblyAsmBackend::getFixupKind(StringRef Name) const {55 unsigned Type = llvm::StringSwitch<unsigned>(Name)56#define WASM_RELOC(NAME, ID) .Case(#NAME, ID)57#include "llvm/BinaryFormat/WasmRelocs.def"58#undef WASM_RELOC59 .Default(-1u);60 if (Type != -1u)61 return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);62 return std::nullopt;63}64 65MCFixupKindInfo66WebAssemblyAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {67 const static MCFixupKindInfo Infos[WebAssembly::NumTargetFixupKinds] = {68 // This table *must* be in the order that the fixup_* kinds are defined in69 // WebAssemblyFixupKinds.h.70 //71 // Name Offset (bits) Size (bits) Flags72 {"fixup_sleb128_i32", 0, 5 * 8, 0},73 {"fixup_sleb128_i64", 0, 10 * 8, 0},74 {"fixup_uleb128_i32", 0, 5 * 8, 0},75 {"fixup_uleb128_i64", 0, 10 * 8, 0},76 };77 78 // Fixup kinds from raw relocation types and .reloc directives force79 // relocations and do not use these fields.80 if (mc::isRelocation(Kind))81 return {};82 83 if (Kind < FirstTargetFixupKind)84 return MCAsmBackend::getFixupKindInfo(Kind);85 86 assert(unsigned(Kind - FirstTargetFixupKind) <87 WebAssembly::NumTargetFixupKinds &&88 "Invalid kind!");89 return Infos[Kind - FirstTargetFixupKind];90}91 92bool WebAssemblyAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,93 const MCSubtargetInfo *STI) const {94 for (uint64_t I = 0; I < Count; ++I)95 OS << char(WebAssembly::Nop);96 97 return true;98}99 100void WebAssemblyAsmBackend::applyFixup(const MCFragment &F,101 const MCFixup &Fixup,102 const MCValue &Target, uint8_t *Data,103 uint64_t Value, bool IsResolved) {104 if (!IsResolved)105 Asm->getWriter().recordRelocation(F, Fixup, Target, Value);106 107 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 assert(Fixup.getOffset() + NumBytes <= F.getSize() &&118 "Invalid fixup offset!");119 120 // For each byte of the fragment that the fixup touches, mask in the121 // bits from the fixup value.122 for (unsigned I = 0; I != NumBytes; ++I)123 Data[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 namespace132 133MCAsmBackend *llvm::createWebAssemblyAsmBackend(const Triple &TT) {134 return new WebAssemblyAsmBackend(TT.isArch64Bit(), TT.isOSEmscripten());135}136