LLVM  8.0.1
WebAssemblyWasmObjectWriter.cpp
Go to the documentation of this file.
1 //===-- WebAssemblyWasmObjectWriter.cpp - WebAssembly Wasm Writer ---------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// This file handles Wasm-specific object emission, converting LLVM's
12 /// internal fixups into the appropriate relocations.
13 ///
14 //===----------------------------------------------------------------------===//
15 
18 #include "llvm/BinaryFormat/Wasm.h"
19 #include "llvm/MC/MCAsmBackend.h"
20 #include "llvm/MC/MCFixup.h"
22 #include "llvm/MC/MCObjectWriter.h"
23 #include "llvm/MC/MCSectionWasm.h"
24 #include "llvm/MC/MCSymbolWasm.h"
25 #include "llvm/MC/MCValue.h"
27 #include "llvm/Support/Casting.h"
29 
30 using namespace llvm;
31 
32 namespace {
33 class WebAssemblyWasmObjectWriter final : public MCWasmObjectTargetWriter {
34 public:
35  explicit WebAssemblyWasmObjectWriter(bool Is64Bit);
36 
37 private:
38  unsigned getRelocType(const MCValue &Target,
39  const MCFixup &Fixup) const override;
40 };
41 } // end anonymous namespace
42 
43 WebAssemblyWasmObjectWriter::WebAssemblyWasmObjectWriter(bool Is64Bit)
44  : MCWasmObjectTargetWriter(Is64Bit) {}
45 
46 // Test whether the given expression computes a function address.
47 static bool IsFunctionExpr(const MCExpr *Expr) {
48  if (auto SyExp = dyn_cast<MCSymbolRefExpr>(Expr))
49  return cast<MCSymbolWasm>(SyExp->getSymbol()).isFunction();
50 
51  if (auto BinOp = dyn_cast<MCBinaryExpr>(Expr))
52  return IsFunctionExpr(BinOp->getLHS()) != IsFunctionExpr(BinOp->getRHS());
53 
54  if (auto UnOp = dyn_cast<MCUnaryExpr>(Expr))
55  return IsFunctionExpr(UnOp->getSubExpr());
56 
57  return false;
58 }
59 
60 static bool IsFunctionType(const MCValue &Target) {
61  const MCSymbolRefExpr *RefA = Target.getSymA();
62  return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_TYPEINDEX;
63 }
64 
65 static const MCSection *GetFixupSection(const MCExpr *Expr) {
66  if (auto SyExp = dyn_cast<MCSymbolRefExpr>(Expr)) {
67  if (SyExp->getSymbol().isInSection())
68  return &SyExp->getSymbol().getSection();
69  return nullptr;
70  }
71 
72  if (auto BinOp = dyn_cast<MCBinaryExpr>(Expr)) {
73  auto SectionLHS = GetFixupSection(BinOp->getLHS());
74  auto SectionRHS = GetFixupSection(BinOp->getRHS());
75  return SectionLHS == SectionRHS ? nullptr : SectionLHS;
76  }
77 
78  if (auto UnOp = dyn_cast<MCUnaryExpr>(Expr))
79  return GetFixupSection(UnOp->getSubExpr());
80 
81  return nullptr;
82 }
83 
84 static bool IsGlobalType(const MCValue &Target) {
85  const MCSymbolRefExpr *RefA = Target.getSymA();
86  return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_GLOBAL;
87 }
88 
89 static bool IsEventType(const MCValue &Target) {
90  const MCSymbolRefExpr *RefA = Target.getSymA();
91  return RefA && RefA->getKind() == MCSymbolRefExpr::VK_WebAssembly_EVENT;
92 }
93 
95  const MCFixup &Fixup) const {
96  // WebAssembly functions are not allocated in the data address space. To
97  // resolve a pointer to a function, we must use a special relocation type.
98  bool IsFunction = IsFunctionExpr(Fixup.getValue());
99 
100  switch (unsigned(Fixup.getKind())) {
102  if (IsFunction)
103  return wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB;
104  return wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB;
106  llvm_unreachable("fixup_sleb128_i64 not implemented yet");
108  if (IsGlobalType(Target))
109  return wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB;
110  if (IsFunctionType(Target))
111  return wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB;
112  if (IsFunction)
113  return wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB;
114  if (IsEventType(Target))
115  return wasm::R_WEBASSEMBLY_EVENT_INDEX_LEB;
116  return wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB;
117  case FK_Data_4:
118  if (IsFunction)
119  return wasm::R_WEBASSEMBLY_TABLE_INDEX_I32;
120  if (auto Section = static_cast<const MCSectionWasm *>(
121  GetFixupSection(Fixup.getValue()))) {
122  if (Section->getKind().isText())
123  return wasm::R_WEBASSEMBLY_FUNCTION_OFFSET_I32;
124  else if (!Section->isWasmData())
125  return wasm::R_WEBASSEMBLY_SECTION_OFFSET_I32;
126  }
127  return wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32;
128  case FK_Data_8:
129  llvm_unreachable("FK_Data_8 not implemented yet");
130  default:
131  llvm_unreachable("unimplemented fixup kind");
132  }
133 }
134 
135 std::unique_ptr<MCObjectTargetWriter>
137  return llvm::make_unique<WebAssemblyWasmObjectWriter>(Is64Bit);
138 }
Instances of this class represent a uniqued identifier for a section in the current translation unit...
Definition: MCSection.h:39
static bool IsGlobalType(const MCValue &Target)
This class represents lattice values for constants.
Definition: AllocatorList.h:24
This represents an "assembler immediate".
Definition: MCValue.h:40
std::unique_ptr< MCObjectTargetWriter > createWebAssemblyWasmObjectWriter(bool Is64Bit)
VariantKind getKind() const
Definition: MCExpr.h:338
static bool IsFunctionType(const MCValue &Target)
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:74
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:36
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:166
static unsigned getRelocType(const MCValue &Target, const MCFixupKind FixupKind, const bool IsPCRel)
Translates generic PPC fixup kind to Mach-O/PPC relocation type enum.
A four-byte fixup.
Definition: MCFixup.h:26
static bool IsEventType(const MCValue &Target)
This file provides WebAssembly-specific target descriptions.
static const MCSection * GetFixupSection(const MCExpr *Expr)
const MCSymbolRefExpr * getSymA() const
Definition: MCValue.h:48
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
PowerPC TLS Dynamic Call Fixup
Target - Wrapper for Target specific information.
A eight-byte fixup.
Definition: MCFixup.h:27
const MCExpr * getValue() const
Definition: MCFixup.h:128
MCFixupKind getKind() const
Definition: MCFixup.h:123
static bool IsFunctionExpr(const MCExpr *Expr)