118eafb6cSDan Gohman //===-- WebAssemblyWasmObjectWriter.cpp - WebAssembly Wasm Writer ---------===// 218eafb6cSDan Gohman // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 618eafb6cSDan Gohman // 718eafb6cSDan Gohman //===----------------------------------------------------------------------===// 818eafb6cSDan Gohman /// 918eafb6cSDan Gohman /// \file 105f8f34e4SAdrian Prantl /// This file handles Wasm-specific object emission, converting LLVM's 1118eafb6cSDan Gohman /// internal fixups into the appropriate relocations. 1218eafb6cSDan Gohman /// 1318eafb6cSDan Gohman //===----------------------------------------------------------------------===// 1418eafb6cSDan Gohman 15d934cb88SDan Gohman #include "MCTargetDesc/WebAssemblyFixupKinds.h" 166bda14b3SChandler Carruth #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 17264b5d9eSZachary Turner #include "llvm/BinaryFormat/Wasm.h" 18ae03c1e7SSam Clegg #include "llvm/MC/MCAsmBackend.h" 1918eafb6cSDan Gohman #include "llvm/MC/MCFixup.h" 20ae03c1e7SSam Clegg #include "llvm/MC/MCFixupKindInfo.h" 21669300dbSDerek Schuff #include "llvm/MC/MCObjectWriter.h" 226a31a0d6SSam Clegg #include "llvm/MC/MCSectionWasm.h" 23d934cb88SDan Gohman #include "llvm/MC/MCSymbolWasm.h" 24ae03c1e7SSam Clegg #include "llvm/MC/MCValue.h" 256a31a0d6SSam Clegg #include "llvm/MC/MCWasmObjectWriter.h" 26d934cb88SDan Gohman #include "llvm/Support/Casting.h" 2718eafb6cSDan Gohman #include "llvm/Support/ErrorHandling.h" 28ae03c1e7SSam Clegg 2918eafb6cSDan Gohman using namespace llvm; 3018eafb6cSDan Gohman 3118eafb6cSDan Gohman namespace { 3218eafb6cSDan Gohman class WebAssemblyWasmObjectWriter final : public MCWasmObjectTargetWriter { 3318eafb6cSDan Gohman public: 34da84b688SDan Gohman explicit WebAssemblyWasmObjectWriter(bool Is64Bit, bool IsEmscripten); 3518eafb6cSDan Gohman 3618eafb6cSDan Gohman private: 37aa0c571aSYuta Saito unsigned getRelocType(const MCValue &Target, const MCFixup &Fixup, 38aa0c571aSYuta Saito bool IsLocRel) const override; 3918eafb6cSDan Gohman }; 4018eafb6cSDan Gohman } // end anonymous namespace 4118eafb6cSDan Gohman 42da84b688SDan Gohman WebAssemblyWasmObjectWriter::WebAssemblyWasmObjectWriter(bool Is64Bit, 43da84b688SDan Gohman bool IsEmscripten) 44da84b688SDan Gohman : MCWasmObjectTargetWriter(Is64Bit, IsEmscripten) {} 4518eafb6cSDan Gohman 4618c56a07SHeejin Ahn static const MCSection *getFixupSection(const MCExpr *Expr) { 476a31a0d6SSam Clegg if (auto SyExp = dyn_cast<MCSymbolRefExpr>(Expr)) { 486a31a0d6SSam Clegg if (SyExp->getSymbol().isInSection()) 496a31a0d6SSam Clegg return &SyExp->getSymbol().getSection(); 506a31a0d6SSam Clegg return nullptr; 516a31a0d6SSam Clegg } 526a31a0d6SSam Clegg 536a31a0d6SSam Clegg if (auto BinOp = dyn_cast<MCBinaryExpr>(Expr)) { 5418c56a07SHeejin Ahn auto SectionLHS = getFixupSection(BinOp->getLHS()); 5518c56a07SHeejin Ahn auto SectionRHS = getFixupSection(BinOp->getRHS()); 566a31a0d6SSam Clegg return SectionLHS == SectionRHS ? nullptr : SectionLHS; 576a31a0d6SSam Clegg } 586a31a0d6SSam Clegg 596a31a0d6SSam Clegg if (auto UnOp = dyn_cast<MCUnaryExpr>(Expr)) 6018c56a07SHeejin Ahn return getFixupSection(UnOp->getSubExpr()); 616a31a0d6SSam Clegg 626a31a0d6SSam Clegg return nullptr; 636a31a0d6SSam Clegg } 646a31a0d6SSam Clegg 65f208f631SHeejin Ahn unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue &Target, 66aa0c571aSYuta Saito const MCFixup &Fixup, 67aa0c571aSYuta Saito bool IsLocRel) const { 688fffa1dfSSam Clegg const MCSymbolRefExpr *RefA = Target.getSymA(); 698fffa1dfSSam Clegg assert(RefA); 708fffa1dfSSam Clegg auto& SymA = cast<MCSymbolWasm>(RefA->getSymbol()); 71d934cb88SDan Gohman 722a7cac93SSam Clegg MCSymbolRefExpr::VariantKind Modifier = Target.getAccessVariant(); 732a7cac93SSam Clegg 742a7cac93SSam Clegg switch (Modifier) { 752a7cac93SSam Clegg case MCSymbolRefExpr::VK_GOT: 762a7cac93SSam Clegg return wasm::R_WASM_GLOBAL_INDEX_LEB; 772a7cac93SSam Clegg case MCSymbolRefExpr::VK_WASM_TBREL: 782a7cac93SSam Clegg assert(SymA.isFunction()); 79*3a293cbfSWouter van Oortmerssen return is64Bit() ? wasm::R_WASM_TABLE_INDEX_REL_SLEB64 80*3a293cbfSWouter van Oortmerssen : wasm::R_WASM_TABLE_INDEX_REL_SLEB; 81a28a4662SSam Clegg case MCSymbolRefExpr::VK_WASM_TLSREL: 82a28a4662SSam Clegg return wasm::R_WASM_MEMORY_ADDR_TLS_SLEB; 832a7cac93SSam Clegg case MCSymbolRefExpr::VK_WASM_MBREL: 842a7cac93SSam Clegg assert(SymA.isData()); 853b29376eSWouter van Oortmerssen return is64Bit() ? wasm::R_WASM_MEMORY_ADDR_REL_SLEB64 863b29376eSWouter van Oortmerssen : wasm::R_WASM_MEMORY_ADDR_REL_SLEB; 872a7cac93SSam Clegg case MCSymbolRefExpr::VK_WASM_TYPEINDEX: 882a7cac93SSam Clegg return wasm::R_WASM_TYPE_INDEX_LEB; 892a7cac93SSam Clegg default: 902a7cac93SSam Clegg break; 912a7cac93SSam Clegg } 922a7cac93SSam Clegg 93d934cb88SDan Gohman switch (unsigned(Fixup.getKind())) { 94a5e175c6SSam Clegg case WebAssembly::fixup_sleb128_i32: 958fffa1dfSSam Clegg if (SymA.isFunction()) 96d1152a26SSam Clegg return wasm::R_WASM_TABLE_INDEX_SLEB; 97d1152a26SSam Clegg return wasm::R_WASM_MEMORY_ADDR_SLEB; 983b29376eSWouter van Oortmerssen case WebAssembly::fixup_sleb128_i64: 99cc1b9b68SWouter van Oortmerssen if (SymA.isFunction()) 100cc1b9b68SWouter van Oortmerssen return wasm::R_WASM_TABLE_INDEX_SLEB64; 1013b29376eSWouter van Oortmerssen return wasm::R_WASM_MEMORY_ADDR_SLEB64; 102a5e175c6SSam Clegg case WebAssembly::fixup_uleb128_i32: 1032a7cac93SSam Clegg if (SymA.isGlobal()) 104492f7529SSam Clegg return wasm::R_WASM_GLOBAL_INDEX_LEB; 1052a7cac93SSam Clegg if (SymA.isFunction()) 106d1152a26SSam Clegg return wasm::R_WASM_FUNCTION_INDEX_LEB; 1078fffa1dfSSam Clegg if (SymA.isEvent()) 108d1152a26SSam Clegg return wasm::R_WASM_EVENT_INDEX_LEB; 10969e2797eSPaulo Matos if (SymA.isTable()) 11069e2797eSPaulo Matos return wasm::R_WASM_TABLE_NUMBER_LEB; 111d1152a26SSam Clegg return wasm::R_WASM_MEMORY_ADDR_LEB; 1123b29376eSWouter van Oortmerssen case WebAssembly::fixup_uleb128_i64: 1133b29376eSWouter van Oortmerssen assert(SymA.isData()); 1143b29376eSWouter van Oortmerssen return wasm::R_WASM_MEMORY_ADDR_LEB64; 115d934cb88SDan Gohman case FK_Data_4: 1168fffa1dfSSam Clegg if (SymA.isFunction()) 117d1152a26SSam Clegg return wasm::R_WASM_TABLE_INDEX_I32; 11848139ebcSWouter van Oortmerssen if (SymA.isGlobal()) 11948139ebcSWouter van Oortmerssen return wasm::R_WASM_GLOBAL_INDEX_I32; 1206a31a0d6SSam Clegg if (auto Section = static_cast<const MCSectionWasm *>( 12118c56a07SHeejin Ahn getFixupSection(Fixup.getValue()))) { 1226a31a0d6SSam Clegg if (Section->getKind().isText()) 123d1152a26SSam Clegg return wasm::R_WASM_FUNCTION_OFFSET_I32; 1246a31a0d6SSam Clegg else if (!Section->isWasmData()) 125d1152a26SSam Clegg return wasm::R_WASM_SECTION_OFFSET_I32; 1266a31a0d6SSam Clegg } 127aa0c571aSYuta Saito return IsLocRel ? wasm::R_WASM_MEMORY_ADDR_LOCREL_I32 128aa0c571aSYuta Saito : wasm::R_WASM_MEMORY_ADDR_I32; 1293b29376eSWouter van Oortmerssen case FK_Data_8: 130cc1b9b68SWouter van Oortmerssen if (SymA.isFunction()) 131cc1b9b68SWouter van Oortmerssen return wasm::R_WASM_TABLE_INDEX_I64; 13286cd2332SWouter van Oortmerssen if (SymA.isGlobal()) 13386cd2332SWouter van Oortmerssen llvm_unreachable("unimplemented R_WASM_GLOBAL_INDEX_I64"); 13486cd2332SWouter van Oortmerssen if (auto Section = static_cast<const MCSectionWasm *>( 13586cd2332SWouter van Oortmerssen getFixupSection(Fixup.getValue()))) { 13686cd2332SWouter van Oortmerssen if (Section->getKind().isText()) 13716f02431SWouter van Oortmerssen return wasm::R_WASM_FUNCTION_OFFSET_I64; 13886cd2332SWouter van Oortmerssen else if (!Section->isWasmData()) 13986cd2332SWouter van Oortmerssen llvm_unreachable("unimplemented R_WASM_SECTION_OFFSET_I64"); 14086cd2332SWouter van Oortmerssen } 1413b29376eSWouter van Oortmerssen assert(SymA.isData()); 1423b29376eSWouter van Oortmerssen return wasm::R_WASM_MEMORY_ADDR_I64; 143d934cb88SDan Gohman default: 144d934cb88SDan Gohman llvm_unreachable("unimplemented fixup kind"); 145d934cb88SDan Gohman } 14618eafb6cSDan Gohman } 14718eafb6cSDan Gohman 148dcd7d6c3SPeter Collingbourne std::unique_ptr<MCObjectTargetWriter> 149da84b688SDan Gohman llvm::createWebAssemblyWasmObjectWriter(bool Is64Bit, bool IsEmscripten) { 150da84b688SDan Gohman return std::make_unique<WebAssemblyWasmObjectWriter>(Is64Bit, IsEmscripten); 15118eafb6cSDan Gohman } 152