Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / lib / Target / WebAssembly / MCTargetDesc / WebAssemblyWasmObjectWriter.cpp
blob2c97aadd7f9edb499fb7345887d29505395a6d30
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file handles Wasm-specific object emission, converting LLVM's
11 /// internal fixups into the appropriate relocations.
12 ///
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"
29 using namespace llvm;
31 namespace {
32 class WebAssemblyWasmObjectWriter final : public MCWasmObjectTargetWriter {
33 public:
34 explicit WebAssemblyWasmObjectWriter(bool Is64Bit);
36 private:
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());
56 return false;
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();
68 return nullptr;
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());
80 return nullptr;
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:
101 if (IsFunction)
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;
111 if (IsFunction)
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;
116 case FK_Data_4:
117 if (IsFunction)
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;
127 case FK_Data_8:
128 llvm_unreachable("FK_Data_8 not implemented yet");
129 default:
130 llvm_unreachable("unimplemented fixup kind");
134 std::unique_ptr<MCObjectTargetWriter>
135 llvm::createWebAssemblyWasmObjectWriter(bool Is64Bit) {
136 return llvm::make_unique<WebAssemblyWasmObjectWriter>(Is64Bit);