118eafb6cSDan Gohman //===-- WebAssemblyWasmObjectWriter.cpp - WebAssembly Wasm Writer ---------===// 218eafb6cSDan Gohman // 318eafb6cSDan Gohman // The LLVM Compiler Infrastructure 418eafb6cSDan Gohman // 518eafb6cSDan Gohman // This file is distributed under the University of Illinois Open Source 618eafb6cSDan Gohman // License. See LICENSE.TXT for details. 718eafb6cSDan Gohman // 818eafb6cSDan Gohman //===----------------------------------------------------------------------===// 918eafb6cSDan Gohman /// 1018eafb6cSDan Gohman /// \file 1118eafb6cSDan Gohman /// \brief This file handles Wasm-specific object emission, converting LLVM's 1218eafb6cSDan Gohman /// internal fixups into the appropriate relocations. 1318eafb6cSDan Gohman /// 1418eafb6cSDan Gohman //===----------------------------------------------------------------------===// 1518eafb6cSDan Gohman 16d934cb88SDan Gohman #include "MCTargetDesc/WebAssemblyFixupKinds.h" 176bda14b3SChandler Carruth #include "MCTargetDesc/WebAssemblyMCTargetDesc.h" 1818eafb6cSDan Gohman #include "llvm/MC/MCFixup.h" 19d934cb88SDan Gohman #include "llvm/MC/MCSymbolWasm.h" 2018eafb6cSDan Gohman #include "llvm/MC/MCWasmObjectWriter.h" 21d934cb88SDan Gohman #include "llvm/Support/Casting.h" 2218eafb6cSDan Gohman #include "llvm/Support/ErrorHandling.h" 23d934cb88SDan Gohman #include "llvm/Support/Wasm.h" 2418eafb6cSDan Gohman using namespace llvm; 2518eafb6cSDan Gohman 2618eafb6cSDan Gohman namespace { 2718eafb6cSDan Gohman class WebAssemblyWasmObjectWriter final : public MCWasmObjectTargetWriter { 2818eafb6cSDan Gohman public: 2918eafb6cSDan Gohman explicit WebAssemblyWasmObjectWriter(bool Is64Bit); 3018eafb6cSDan Gohman 3118eafb6cSDan Gohman private: 3218eafb6cSDan Gohman unsigned getRelocType(MCContext &Ctx, const MCValue &Target, 3318eafb6cSDan Gohman const MCFixup &Fixup, bool IsPCRel) const override; 3418eafb6cSDan Gohman }; 3518eafb6cSDan Gohman } // end anonymous namespace 3618eafb6cSDan Gohman 3718eafb6cSDan Gohman WebAssemblyWasmObjectWriter::WebAssemblyWasmObjectWriter(bool Is64Bit) 3818eafb6cSDan Gohman : MCWasmObjectTargetWriter(Is64Bit) {} 3918eafb6cSDan Gohman 40d934cb88SDan Gohman // Test whether the given expression computes a function address. 41d934cb88SDan Gohman static bool IsFunctionExpr(const MCExpr *Expr) { 42d934cb88SDan Gohman if (const MCSymbolRefExpr *SyExp = 43d934cb88SDan Gohman dyn_cast<MCSymbolRefExpr>(Expr)) 44d934cb88SDan Gohman return cast<MCSymbolWasm>(SyExp->getSymbol()).isFunction(); 45d934cb88SDan Gohman 46d934cb88SDan Gohman if (const MCBinaryExpr *BinOp = 47d934cb88SDan Gohman dyn_cast<MCBinaryExpr>(Expr)) 48d934cb88SDan Gohman return IsFunctionExpr(BinOp->getLHS()) != IsFunctionExpr(BinOp->getRHS()); 49d934cb88SDan Gohman 50d934cb88SDan Gohman if (const MCUnaryExpr *UnOp = 51d934cb88SDan Gohman dyn_cast<MCUnaryExpr>(Expr)) 52d934cb88SDan Gohman return IsFunctionExpr(UnOp->getSubExpr()); 53d934cb88SDan Gohman 54d934cb88SDan Gohman return false; 55d934cb88SDan Gohman } 56d934cb88SDan Gohman 57*acd7d2b0SSam Clegg static bool IsFunctionType(const MCValue &Target) { 58*acd7d2b0SSam Clegg const MCSymbolRefExpr *RefA = Target.getSymA(); 59*acd7d2b0SSam Clegg return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_TYPEINDEX; 60*acd7d2b0SSam Clegg } 61*acd7d2b0SSam Clegg 6218eafb6cSDan Gohman unsigned WebAssemblyWasmObjectWriter::getRelocType(MCContext &Ctx, 6318eafb6cSDan Gohman const MCValue &Target, 6418eafb6cSDan Gohman const MCFixup &Fixup, 6518eafb6cSDan Gohman bool IsPCRel) const { 66d934cb88SDan Gohman // WebAssembly functions are not allocated in the data address space. To 67d934cb88SDan Gohman // resolve a pointer to a function, we must use a special relocation type. 68d934cb88SDan Gohman bool IsFunction = IsFunctionExpr(Fixup.getValue()); 69d934cb88SDan Gohman 70d934cb88SDan Gohman assert(!IsPCRel); 71d934cb88SDan Gohman switch (unsigned(Fixup.getKind())) { 72d934cb88SDan Gohman case WebAssembly::fixup_code_sleb128_i32: 73d934cb88SDan Gohman if (IsFunction) 74d934cb88SDan Gohman return wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB; 75d934cb88SDan Gohman return wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB; 76d934cb88SDan Gohman case WebAssembly::fixup_code_sleb128_i64: 77d934cb88SDan Gohman llvm_unreachable("fixup_sleb128_i64 not implemented yet"); 78d934cb88SDan Gohman case WebAssembly::fixup_code_uleb128_i32: 79*acd7d2b0SSam Clegg if (IsFunctionType(Target)) 80*acd7d2b0SSam Clegg return wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB; 81d934cb88SDan Gohman if (IsFunction) 82d934cb88SDan Gohman return wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB; 83d934cb88SDan Gohman return wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB; 84d934cb88SDan Gohman case FK_Data_4: 85d934cb88SDan Gohman if (IsFunction) 86d934cb88SDan Gohman return wasm::R_WEBASSEMBLY_TABLE_INDEX_I32; 87d934cb88SDan Gohman return wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32; 88d934cb88SDan Gohman case FK_Data_8: 89d934cb88SDan Gohman llvm_unreachable("FK_Data_8 not implemented yet"); 90d934cb88SDan Gohman default: 91d934cb88SDan Gohman llvm_unreachable("unimplemented fixup kind"); 92d934cb88SDan Gohman } 9318eafb6cSDan Gohman } 9418eafb6cSDan Gohman 9518eafb6cSDan Gohman MCObjectWriter *llvm::createWebAssemblyWasmObjectWriter(raw_pwrite_stream &OS, 9618eafb6cSDan Gohman bool Is64Bit) { 9718eafb6cSDan Gohman MCWasmObjectTargetWriter *MOTW = new WebAssemblyWasmObjectWriter(Is64Bit); 9818eafb6cSDan Gohman return createWasmObjectWriter(MOTW, OS); 9918eafb6cSDan Gohman } 100