brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.6 KiB · 65035df Raw
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