brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.8 KiB · ffbc7e1 Raw
165 lines · cpp
1//===-- WebAssemblyWasmObjectWriter.cpp - WebAssembly Wasm Writer ---------===//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 handles Wasm-specific object emission, converting LLVM's11/// internal fixups into the appropriate relocations.12///13//===----------------------------------------------------------------------===//14 15#include "MCTargetDesc/WebAssemblyFixupKinds.h"16#include "MCTargetDesc/WebAssemblyMCAsmInfo.h"17#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"18#include "llvm/BinaryFormat/Wasm.h"19#include "llvm/MC/MCAsmBackend.h"20#include "llvm/MC/MCFixup.h"21#include "llvm/MC/MCObjectWriter.h"22#include "llvm/MC/MCSectionWasm.h"23#include "llvm/MC/MCSymbolWasm.h"24#include "llvm/MC/MCValue.h"25#include "llvm/MC/MCWasmObjectWriter.h"26#include "llvm/Support/Casting.h"27#include "llvm/Support/ErrorHandling.h"28 29using namespace llvm;30 31namespace {32class WebAssemblyWasmObjectWriter final : public MCWasmObjectTargetWriter {33public:34  explicit WebAssemblyWasmObjectWriter(bool Is64Bit, bool IsEmscripten);35 36private:37  unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup,38                        const MCSectionWasm &FixupSection,39                        bool IsLocRel) const override;40};41} // end anonymous namespace42 43WebAssemblyWasmObjectWriter::WebAssemblyWasmObjectWriter(bool Is64Bit,44                                                         bool IsEmscripten)45    : MCWasmObjectTargetWriter(Is64Bit, IsEmscripten) {}46 47static const MCSection *getTargetSection(const MCExpr *Expr) {48  if (auto SyExp = dyn_cast<MCSymbolRefExpr>(Expr)) {49    if (SyExp->getSymbol().isInSection())50      return &SyExp->getSymbol().getSection();51    return nullptr;52  }53 54  if (auto BinOp = dyn_cast<MCBinaryExpr>(Expr)) {55    auto SectionLHS = getTargetSection(BinOp->getLHS());56    auto SectionRHS = getTargetSection(BinOp->getRHS());57    return SectionLHS == SectionRHS ? nullptr : SectionLHS;58  }59 60  if (auto UnOp = dyn_cast<MCUnaryExpr>(Expr))61    return getTargetSection(UnOp->getSubExpr());62 63  return nullptr;64}65 66unsigned WebAssemblyWasmObjectWriter::getRelocType(67    const MCValue &Target, const MCFixup &Fixup,68    const MCSectionWasm &FixupSection, bool IsLocRel) const {69  auto &SymA = static_cast<const MCSymbolWasm &>(*Target.getAddSym());70  auto Spec = WebAssembly::Specifier(Target.getSpecifier());71  switch (Spec) {72  case WebAssembly::S_GOT:73    SymA.setUsedInGOT();74    return wasm::R_WASM_GLOBAL_INDEX_LEB;75  case WebAssembly::S_GOT_TLS:76    SymA.setUsedInGOT();77    SymA.setTLS();78    return wasm::R_WASM_GLOBAL_INDEX_LEB;79  case WebAssembly::S_TBREL:80    assert(SymA.isFunction());81    return is64Bit() ? wasm::R_WASM_TABLE_INDEX_REL_SLEB6482                     : wasm::R_WASM_TABLE_INDEX_REL_SLEB;83  case WebAssembly::S_TLSREL:84    SymA.setTLS();85    return is64Bit() ? wasm::R_WASM_MEMORY_ADDR_TLS_SLEB6486                     : wasm::R_WASM_MEMORY_ADDR_TLS_SLEB;87  case WebAssembly::S_MBREL:88    assert(SymA.isData());89    return is64Bit() ? wasm::R_WASM_MEMORY_ADDR_REL_SLEB6490                     : wasm::R_WASM_MEMORY_ADDR_REL_SLEB;91  case WebAssembly::S_TYPEINDEX:92    return wasm::R_WASM_TYPE_INDEX_LEB;93  case WebAssembly::S_None:94    break;95  case WebAssembly::S_FUNCINDEX:96    return wasm::R_WASM_FUNCTION_INDEX_I32;97  }98 99  switch (unsigned(Fixup.getKind())) {100  case WebAssembly::fixup_sleb128_i32:101    if (SymA.isFunction())102      return wasm::R_WASM_TABLE_INDEX_SLEB;103    return wasm::R_WASM_MEMORY_ADDR_SLEB;104  case WebAssembly::fixup_sleb128_i64:105    if (SymA.isFunction())106      return wasm::R_WASM_TABLE_INDEX_SLEB64;107    return wasm::R_WASM_MEMORY_ADDR_SLEB64;108  case WebAssembly::fixup_uleb128_i32:109    if (SymA.isGlobal())110      return wasm::R_WASM_GLOBAL_INDEX_LEB;111    if (SymA.isFunction())112      return wasm::R_WASM_FUNCTION_INDEX_LEB;113    if (SymA.isTag())114      return wasm::R_WASM_TAG_INDEX_LEB;115    if (SymA.isTable())116      return wasm::R_WASM_TABLE_NUMBER_LEB;117    return wasm::R_WASM_MEMORY_ADDR_LEB;118  case WebAssembly::fixup_uleb128_i64:119    assert(SymA.isData());120    return wasm::R_WASM_MEMORY_ADDR_LEB64;121  case FK_Data_4:122    if (SymA.isFunction()) {123      if (FixupSection.isMetadata())124        return wasm::R_WASM_FUNCTION_OFFSET_I32;125      assert(FixupSection.isWasmData());126      return wasm::R_WASM_TABLE_INDEX_I32;127    }128    if (SymA.isGlobal())129      return wasm::R_WASM_GLOBAL_INDEX_I32;130    if (auto Section = static_cast<const MCSectionWasm *>(131            getTargetSection(Fixup.getValue()))) {132      if (Section->isText())133        return wasm::R_WASM_FUNCTION_OFFSET_I32;134      else if (!Section->isWasmData())135        return wasm::R_WASM_SECTION_OFFSET_I32;136    }137    return IsLocRel ? wasm::R_WASM_MEMORY_ADDR_LOCREL_I32138                    : wasm::R_WASM_MEMORY_ADDR_I32;139  case FK_Data_8:140    if (SymA.isFunction()) {141      if (FixupSection.isMetadata())142        return wasm::R_WASM_FUNCTION_OFFSET_I64;143      return wasm::R_WASM_TABLE_INDEX_I64;144    }145    if (SymA.isGlobal())146      llvm_unreachable("unimplemented R_WASM_GLOBAL_INDEX_I64");147    if (auto Section = static_cast<const MCSectionWasm *>(148            getTargetSection(Fixup.getValue()))) {149      if (Section->isText())150        return wasm::R_WASM_FUNCTION_OFFSET_I64;151      else if (!Section->isWasmData())152        llvm_unreachable("unimplemented R_WASM_SECTION_OFFSET_I64");153    }154    assert(SymA.isData());155    return wasm::R_WASM_MEMORY_ADDR_I64;156  default:157    llvm_unreachable("unimplemented fixup kind");158  }159}160 161std::unique_ptr<MCObjectTargetWriter>162llvm::createWebAssemblyWasmObjectWriter(bool Is64Bit, bool IsEmscripten) {163  return std::make_unique<WebAssemblyWasmObjectWriter>(Is64Bit, IsEmscripten);164}165