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
);
37 unsigned getRelocType(const MCValue
&Target
,
38 const MCFixup
&Fixup
) const override
;
40 } // end anonymous namespace
42 WebAssemblyWasmObjectWriter::WebAssemblyWasmObjectWriter(bool Is64Bit
)
43 : MCWasmObjectTargetWriter(Is64Bit
) {}
45 // Test whether the given expression computes a function address.
46 static bool isFunctionExpr(const MCExpr
*Expr
) {
47 if (auto SyExp
= dyn_cast
<MCSymbolRefExpr
>(Expr
))
48 return cast
<MCSymbolWasm
>(SyExp
->getSymbol()).isFunction();
50 if (auto BinOp
= dyn_cast
<MCBinaryExpr
>(Expr
))
51 return isFunctionExpr(BinOp
->getLHS()) != isFunctionExpr(BinOp
->getRHS());
53 if (auto UnOp
= dyn_cast
<MCUnaryExpr
>(Expr
))
54 return isFunctionExpr(UnOp
->getSubExpr());
59 static bool isFunctionType(const MCValue
&Target
) {
60 const MCSymbolRefExpr
*RefA
= Target
.getSymA();
61 return RefA
&& RefA
->getKind() == MCSymbolRefExpr::VK_WebAssembly_TYPEINDEX
;
64 static const MCSection
*getFixupSection(const MCExpr
*Expr
) {
65 if (auto SyExp
= dyn_cast
<MCSymbolRefExpr
>(Expr
)) {
66 if (SyExp
->getSymbol().isInSection())
67 return &SyExp
->getSymbol().getSection();
71 if (auto BinOp
= dyn_cast
<MCBinaryExpr
>(Expr
)) {
72 auto SectionLHS
= getFixupSection(BinOp
->getLHS());
73 auto SectionRHS
= getFixupSection(BinOp
->getRHS());
74 return SectionLHS
== SectionRHS
? nullptr : SectionLHS
;
77 if (auto UnOp
= dyn_cast
<MCUnaryExpr
>(Expr
))
78 return getFixupSection(UnOp
->getSubExpr());
83 static bool isGlobalType(const MCValue
&Target
) {
84 const MCSymbolRefExpr
*RefA
= Target
.getSymA();
85 return RefA
&& RefA
->getKind() == MCSymbolRefExpr::VK_WebAssembly_GLOBAL
;
88 static bool isEventType(const MCValue
&Target
) {
89 const MCSymbolRefExpr
*RefA
= Target
.getSymA();
90 return RefA
&& RefA
->getKind() == MCSymbolRefExpr::VK_WebAssembly_EVENT
;
93 unsigned WebAssemblyWasmObjectWriter::getRelocType(const MCValue
&Target
,
94 const MCFixup
&Fixup
) const {
95 // WebAssembly functions are not allocated in the data address space. To
96 // resolve a pointer to a function, we must use a special relocation type.
97 bool IsFunction
= isFunctionExpr(Fixup
.getValue());
99 switch (unsigned(Fixup
.getKind())) {
100 case WebAssembly::fixup_code_sleb128_i32
:
102 return wasm::R_WASM_TABLE_INDEX_SLEB
;
103 return wasm::R_WASM_MEMORY_ADDR_SLEB
;
104 case WebAssembly::fixup_code_sleb128_i64
:
105 llvm_unreachable("fixup_sleb128_i64 not implemented yet");
106 case WebAssembly::fixup_code_uleb128_i32
:
107 if (isGlobalType(Target
))
108 return wasm::R_WASM_GLOBAL_INDEX_LEB
;
109 if (isFunctionType(Target
))
110 return wasm::R_WASM_TYPE_INDEX_LEB
;
112 return wasm::R_WASM_FUNCTION_INDEX_LEB
;
113 if (isEventType(Target
))
114 return wasm::R_WASM_EVENT_INDEX_LEB
;
115 return wasm::R_WASM_MEMORY_ADDR_LEB
;
118 return wasm::R_WASM_TABLE_INDEX_I32
;
119 if (auto Section
= static_cast<const MCSectionWasm
*>(
120 getFixupSection(Fixup
.getValue()))) {
121 if (Section
->getKind().isText())
122 return wasm::R_WASM_FUNCTION_OFFSET_I32
;
123 else if (!Section
->isWasmData())
124 return wasm::R_WASM_SECTION_OFFSET_I32
;
126 return wasm::R_WASM_MEMORY_ADDR_I32
;
128 llvm_unreachable("FK_Data_8 not implemented yet");
130 llvm_unreachable("unimplemented fixup kind");
134 std::unique_ptr
<MCObjectTargetWriter
>
135 llvm::createWebAssemblyWasmObjectWriter(bool Is64Bit
) {
136 return llvm::make_unique
<WebAssemblyWasmObjectWriter
>(Is64Bit
);