1 //===-- WebAssemblyWasmObjectWriter.cpp - WebAssembly Wasm Writer ---------===//
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-exception
7 //===----------------------------------------------------------------------===//
10 /// This file handles Wasm-specific object emission, converting LLVM's
11 /// internal fixups into the appropriate relocations.
13 //===----------------------------------------------------------------------===//
15 #include "MCTargetDesc/WebAssemblyFixupKinds.h"
16 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
17 #include "llvm/BinaryFormat/Wasm.h"
18 #include "llvm/MC/MCAsmBackend.h"
19 #include "llvm/MC/MCFixup.h"
20 #include "llvm/MC/MCFixupKindInfo.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"
32 class WebAssemblyWasmObjectWriter final
: public MCWasmObjectTargetWriter
{
34 explicit WebAssemblyWasmObjectWriter(bool Is64Bit
, bool IsEmscripten
);
37 unsigned getRelocType(const MCValue
&Target
,
38 const MCFixup
&Fixup
) const override
;
40 } // end anonymous namespace
42 WebAssemblyWasmObjectWriter::WebAssemblyWasmObjectWriter(bool Is64Bit
,
44 : MCWasmObjectTargetWriter(Is64Bit
, IsEmscripten
) {}
46 static const MCSection
*getFixupSection(const MCExpr
*Expr
) {
47 if (auto SyExp
= dyn_cast
<MCSymbolRefExpr
>(Expr
)) {
48 if (SyExp
->getSymbol().isInSection())
49 return &SyExp
->getSymbol().getSection();
53 if (auto BinOp
= dyn_cast
<MCBinaryExpr
>(Expr
)) {
54 auto SectionLHS
= getFixupSection(BinOp
->getLHS());
55 auto SectionRHS
= getFixupSection(BinOp
->getRHS());
56 return SectionLHS
== SectionRHS
? nullptr : SectionLHS
;
59 if (auto UnOp
= dyn_cast
<MCUnaryExpr
>(Expr
))
60 return getFixupSection(UnOp
->getSubExpr());
65 unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue
&Target
,
66 const MCFixup
&Fixup
) const {
67 const MCSymbolRefExpr
*RefA
= Target
.getSymA();
69 auto& SymA
= cast
<MCSymbolWasm
>(RefA
->getSymbol());
71 MCSymbolRefExpr::VariantKind Modifier
= Target
.getAccessVariant();
74 case MCSymbolRefExpr::VK_GOT
:
75 return wasm::R_WASM_GLOBAL_INDEX_LEB
;
76 case MCSymbolRefExpr::VK_WASM_TBREL
:
77 assert(SymA
.isFunction());
78 return wasm::R_WASM_TABLE_INDEX_REL_SLEB
;
79 case MCSymbolRefExpr::VK_WASM_MBREL
:
80 assert(SymA
.isData());
81 return wasm::R_WASM_MEMORY_ADDR_REL_SLEB
;
82 case MCSymbolRefExpr::VK_WASM_TYPEINDEX
:
83 return wasm::R_WASM_TYPE_INDEX_LEB
;
88 switch (unsigned(Fixup
.getKind())) {
89 case WebAssembly::fixup_sleb128_i32
:
90 if (SymA
.isFunction())
91 return wasm::R_WASM_TABLE_INDEX_SLEB
;
92 return wasm::R_WASM_MEMORY_ADDR_SLEB
;
93 case WebAssembly::fixup_sleb128_i64
:
94 llvm_unreachable("fixup_sleb128_i64 not implemented yet");
95 case WebAssembly::fixup_uleb128_i32
:
97 return wasm::R_WASM_GLOBAL_INDEX_LEB
;
98 if (SymA
.isFunction())
99 return wasm::R_WASM_FUNCTION_INDEX_LEB
;
101 return wasm::R_WASM_EVENT_INDEX_LEB
;
102 return wasm::R_WASM_MEMORY_ADDR_LEB
;
104 if (SymA
.isFunction())
105 return wasm::R_WASM_TABLE_INDEX_I32
;
106 if (auto Section
= static_cast<const MCSectionWasm
*>(
107 getFixupSection(Fixup
.getValue()))) {
108 if (Section
->getKind().isText())
109 return wasm::R_WASM_FUNCTION_OFFSET_I32
;
110 else if (!Section
->isWasmData())
111 return wasm::R_WASM_SECTION_OFFSET_I32
;
113 return wasm::R_WASM_MEMORY_ADDR_I32
;
115 llvm_unreachable("unimplemented fixup kind");
119 std::unique_ptr
<MCObjectTargetWriter
>
120 llvm::createWebAssemblyWasmObjectWriter(bool Is64Bit
, bool IsEmscripten
) {
121 return std::make_unique
<WebAssemblyWasmObjectWriter
>(Is64Bit
, IsEmscripten
);