LLVM  16.0.0git
WebAssemblyUtilities.cpp
Go to the documentation of this file.
1 //===-- WebAssemblyUtilities.cpp - WebAssembly Utility Functions ----------===//
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 implements several utility functions for WebAssembly.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #include "WebAssemblyUtilities.h"
18 #include "llvm/MC/MCContext.h"
19 using namespace llvm;
20 
21 // Exception handling & setjmp-longjmp handling related options. These are
22 // defined here to be shared between WebAssembly and its subdirectories.
23 
24 // Emscripten's asm.js-style exception handling
26  "enable-emscripten-cxx-exceptions",
27  cl::desc("WebAssembly Emscripten-style exception handling"),
28  cl::init(false));
29 // Emscripten's asm.js-style setjmp/longjmp handling
31  "enable-emscripten-sjlj",
32  cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"),
33  cl::init(false));
34 // Exception handling using wasm EH instructions
36  WebAssembly::WasmEnableEH("wasm-enable-eh",
37  cl::desc("WebAssembly exception handling"),
38  cl::init(false));
39 // setjmp/longjmp handling using wasm EH instrutions
41  WebAssembly::WasmEnableSjLj("wasm-enable-sjlj",
42  cl::desc("WebAssembly setjmp/longjmp handling"),
43  cl::init(false));
44 
45 // Function names in libc++abi and libunwind
46 const char *const WebAssembly::CxaBeginCatchFn = "__cxa_begin_catch";
47 const char *const WebAssembly::CxaRethrowFn = "__cxa_rethrow";
48 const char *const WebAssembly::StdTerminateFn = "_ZSt9terminatev";
50  "_Unwind_Wasm_CallPersonality";
51 
52 /// Test whether MI is a child of some other node in an expression tree.
54  const WebAssemblyFunctionInfo &MFI) {
55  if (MI.getNumOperands() == 0)
56  return false;
57  const MachineOperand &MO = MI.getOperand(0);
58  if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
59  return false;
60  Register Reg = MO.getReg();
62 }
63 
65  switch (MI.getOpcode()) {
66  case WebAssembly::THROW:
67  case WebAssembly::THROW_S:
68  case WebAssembly::RETHROW:
69  case WebAssembly::RETHROW_S:
70  return true;
71  }
72  if (isCallIndirect(MI.getOpcode()))
73  return true;
74  if (!MI.isCall())
75  return false;
76 
77  const MachineOperand &MO = getCalleeOp(MI);
78  assert(MO.isGlobal() || MO.isSymbol());
79 
80  if (MO.isSymbol()) {
81  // Some intrinsics are lowered to calls to external symbols, which are then
82  // lowered to calls to library functions. Most of libcalls don't throw, but
83  // we only list some of them here now.
84  // TODO Consider adding 'nounwind' info in TargetLowering::CallLoweringInfo
85  // instead for more accurate info.
86  const char *Name = MO.getSymbolName();
87  if (strcmp(Name, "memcpy") == 0 || strcmp(Name, "memmove") == 0 ||
88  strcmp(Name, "memset") == 0)
89  return false;
90  return true;
91  }
92 
93  const auto *F = dyn_cast<Function>(MO.getGlobal());
94  if (!F)
95  return true;
96  if (F->doesNotThrow())
97  return false;
98  // These functions never throw
99  if (F->getName() == CxaBeginCatchFn || F->getName() == PersonalityWrapperFn ||
100  F->getName() == StdTerminateFn)
101  return false;
102 
103  // TODO Can we exclude call instructions that are marked as 'nounwind' in the
104  // original LLVm IR? (Even when the callee may throw)
105  return true;
106 }
107 
109  switch (MI.getOpcode()) {
110  case WebAssembly::CALL:
111  case WebAssembly::CALL_S:
112  case WebAssembly::RET_CALL:
113  case WebAssembly::RET_CALL_S:
114  return MI.getOperand(MI.getNumExplicitDefs());
115  case WebAssembly::CALL_INDIRECT:
116  case WebAssembly::CALL_INDIRECT_S:
117  case WebAssembly::RET_CALL_INDIRECT:
118  case WebAssembly::RET_CALL_INDIRECT_S:
119  return MI.getOperand(MI.getNumExplicitOperands() - 1);
120  default:
121  llvm_unreachable("Not a call instruction");
122  }
123 }
124 
126  MCContext &Ctx, const WebAssemblySubtarget *Subtarget) {
127  StringRef Name = "__indirect_function_table";
128  MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(Name));
129  if (Sym) {
130  if (!Sym->isFunctionTable())
131  Ctx.reportError(SMLoc(), "symbol is not a wasm funcref table");
132  } else {
133  Sym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(Name));
134  Sym->setFunctionTable();
135  // The default function table is synthesized by the linker.
136  Sym->setUndefined();
137  }
138  // MVP object files can't have symtab entries for tables.
139  if (!(Subtarget && Subtarget->hasReferenceTypes()))
141  return Sym;
142 }
143 
145  MCContext &Ctx, const WebAssemblySubtarget *Subtarget) {
146  StringRef Name = "__funcref_call_table";
147  MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(Name));
148  if (Sym) {
149  if (!Sym->isFunctionTable())
150  Ctx.reportError(SMLoc(), "symbol is not a wasm funcref table");
151  } else {
152  Sym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(Name));
153 
154  // Setting Weak ensure only one table is left after linking when multiple
155  // modules define the table.
156  Sym->setWeak(true);
157 
158  wasm::WasmLimits Limits = {0, 1, 1};
159  wasm::WasmTableType TableType = {wasm::WASM_TYPE_FUNCREF, Limits};
161  Sym->setTableType(TableType);
162  }
163  // MVP object files can't have symtab entries for tables.
164  if (!(Subtarget && Subtarget->hasReferenceTypes()))
166  return Sym;
167 }
168 
169 // Find a catch instruction from an EH pad.
171  assert(EHPad->isEHPad());
172  auto Pos = EHPad->begin();
173  // Skip any label or debug instructions. Also skip 'end' marker instructions
174  // that may exist after marker placement in CFGStackify.
175  while (Pos != EHPad->end() &&
176  (Pos->isLabel() || Pos->isDebugInstr() || isMarker(Pos->getOpcode())))
177  Pos++;
178  if (Pos != EHPad->end() && WebAssembly::isCatch(Pos->getOpcode()))
179  return &*Pos;
180  return nullptr;
181 }
182 
184  assert(RC != nullptr);
185  switch (RC->getID()) {
186  case WebAssembly::I32RegClassID:
187  return WebAssembly::COPY_I32;
188  case WebAssembly::I64RegClassID:
189  return WebAssembly::COPY_I64;
190  case WebAssembly::F32RegClassID:
191  return WebAssembly::COPY_F32;
192  case WebAssembly::F64RegClassID:
193  return WebAssembly::COPY_F64;
194  case WebAssembly::V128RegClassID:
195  return WebAssembly::COPY_V128;
196  case WebAssembly::FUNCREFRegClassID:
197  return WebAssembly::COPY_FUNCREF;
198  case WebAssembly::EXTERNREFRegClassID:
199  return WebAssembly::COPY_EXTERNREF;
200  default:
201  llvm_unreachable("Unexpected register class");
202  }
203 }
llvm::WebAssembly::isChild
bool isChild(const MachineInstr &MI, const WebAssemblyFunctionInfo &MFI)
Test whether MI is a child of some other node in an expression tree.
Definition: WebAssemblyUtilities.cpp:53
llvm::WebAssembly::getCalleeOp
const MachineOperand & getCalleeOp(const MachineInstr &MI)
Returns the operand number of a callee, assuming the argument is a call instruction.
Definition: WebAssemblyUtilities.cpp:108
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:108
MachineInstr.h
llvm::TargetRegisterClass::getID
unsigned getID() const
Return the register class ID number.
Definition: TargetRegisterInfo.h:75
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::WebAssembly::isCatch
bool isCatch(unsigned Opc)
Definition: WebAssemblyMCTargetDesc.h:407
llvm::WebAssembly::findCatch
MachineInstr * findCatch(MachineBasicBlock *EHPad)
Find a catch instruction from an EH pad.
Definition: WebAssemblyUtilities.cpp:170
llvm::MachineOperand::getGlobal
const GlobalValue * getGlobal() const
Definition: MachineOperand.h:572
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:76
llvm::MCSymbolWasm::setOmitFromLinkingSection
void setOmitFromLinkingSection()
Definition: MCSymbolWasm.h:87
llvm::WebAssembly::getOrCreateFunctionTableSymbol
MCSymbolWasm * getOrCreateFunctionTableSymbol(MCContext &Ctx, const WebAssemblySubtarget *Subtarget)
Returns the __indirect_function_table, for use in call_indirect and in function bitcasts.
Definition: WebAssemblyUtilities.cpp:125
llvm::X86Disassembler::Reg
Reg
All possible values of the reg field in the ModR/M byte.
Definition: X86DisassemblerDecoder.h:462
llvm::wasm::WASM_SYMBOL_TYPE_TABLE
@ WASM_SYMBOL_TYPE_TABLE
Definition: Wasm.h:388
llvm::WebAssembly::mayThrow
bool mayThrow(const MachineInstr &MI)
Definition: WebAssemblyUtilities.cpp:64
llvm::MCSymbol::setUndefined
void setUndefined()
Mark the symbol as undefined.
Definition: MCSymbol.h:274
llvm::MachineOperand::isSymbol
bool isSymbol() const
isSymbol - Tests if this is a MO_ExternalSymbol operand.
Definition: MachineOperand.h:340
llvm::AArch64ISD::CALL
@ CALL
Definition: AArch64ISelLowering.h:53
llvm::WebAssembly::isMarker
bool isMarker(unsigned Opc)
Definition: WebAssemblyMCTargetDesc.h:387
llvm::MCContext::lookupSymbol
MCSymbol * lookupSymbol(const Twine &Name) const
Get the symbol for Name, or null.
Definition: MCContext.cpp:365
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::MCContext::getOrCreateSymbol
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:207
llvm::MachineOperand::isImplicit
bool isImplicit() const
Definition: MachineOperand.h:379
MachineLoopInfo.h
llvm::SMLoc
Represents a location in source code.
Definition: SMLoc.h:23
llvm::wasm::WasmLimits
Definition: Wasm.h:77
MCContext.h
llvm::TargetRegisterClass
Definition: TargetRegisterInfo.h:46
llvm::WebAssembly::WasmEnableEmSjLj
cl::opt< bool > WasmEnableEmSjLj
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:48
llvm::MCSymbolWasm::setType
void setType(wasm::WasmSymbolType type)
Definition: MCSymbolWasm.h:53
llvm::WebAssembly::getCopyOpcodeForRegClass
unsigned getCopyOpcodeForRegClass(const TargetRegisterClass *RC)
Returns the appropriate copy opcode for the given register class.
Definition: WebAssemblyUtilities.cpp:183
llvm::WebAssembly::StdTerminateFn
const char *const StdTerminateFn
Definition: WebAssemblyUtilities.cpp:48
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:94
WebAssemblyUtilities.h
llvm::WebAssembly::CxaBeginCatchFn
const char *const CxaBeginCatchFn
Definition: WebAssemblyUtilities.cpp:46
llvm::cl::opt< bool >
llvm::WebAssemblySubtarget::hasReferenceTypes
bool hasReferenceTypes() const
Definition: WebAssemblySubtarget.h:103
llvm::MCSymbolWasm::setTableType
void setTableType(wasm::WasmTableType TT)
Definition: MCSymbolWasm.h:142
llvm::MachineOperand::isReg
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Definition: MachineOperand.h:320
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:66
llvm::MCSymbolWasm
Definition: MCSymbolWasm.h:16
llvm::WebAssembly::CxaRethrowFn
const char *const CxaRethrowFn
Definition: WebAssemblyUtilities.cpp:47
llvm::MCSymbolWasm::setWeak
void setWeak(bool isWeak)
Definition: MCSymbolWasm.h:75
llvm::cl::init
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:440
llvm::WebAssembly::WasmEnableSjLj
cl::opt< bool > WasmEnableSjLj
llvm::Register::isVirtualRegister
static bool isVirtualRegister(unsigned Reg)
Return true if the specified register number is in the virtual register namespace.
Definition: Register.h:71
llvm::WebAssemblyFunctionInfo::isVRegStackified
bool isVRegStackified(unsigned VReg) const
Definition: WebAssemblyMachineFunctionInfo.h:141
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::WebAssembly::isCallIndirect
bool isCallIndirect(unsigned Opc)
Definition: WebAssemblyMCTargetDesc.h:363
llvm::MCContext::reportError
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1053
llvm::WebAssemblyFunctionInfo
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
Definition: WebAssemblyMachineFunctionInfo.h:33
llvm::MachineOperand::getReg
Register getReg() const
getReg - Returns the register number.
Definition: MachineOperand.h:359
WebAssemblyMachineFunctionInfo.h
llvm::MachineBasicBlock::isEHPad
bool isEHPad() const
Returns true if the block is a landing pad.
Definition: MachineBasicBlock.h:576
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
llvm::MachineOperand::isDef
bool isDef() const
Definition: MachineOperand.h:374
llvm::WebAssemblySubtarget
Definition: WebAssemblySubtarget.h:35
llvm::WebAssembly::PersonalityWrapperFn
const char *const PersonalityWrapperFn
Definition: WebAssemblyUtilities.cpp:49
llvm::WebAssembly::WasmEnableEH
cl::opt< bool > WasmEnableEH
llvm::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
llvm::MCSymbolWasm::isFunctionTable
bool isFunctionTable() const
Definition: MCSymbolWasm.h:113
llvm::WebAssembly::getOrCreateFuncrefCallTableSymbol
MCSymbolWasm * getOrCreateFuncrefCallTableSymbol(MCContext &Ctx, const WebAssemblySubtarget *Subtarget)
Returns the __funcref_call_table, for use in funcref calls when lowered to table.set + call_indirect.
Definition: WebAssemblyUtilities.cpp:144
llvm::MCSymbolWasm::setFunctionTable
void setFunctionTable()
Definition: MCSymbolWasm.h:117
llvm::MachineBasicBlock::begin
iterator begin()
Definition: MachineBasicBlock.h:305
llvm::MachineOperand::getSymbolName
const char * getSymbolName() const
Definition: MachineOperand.h:617
llvm::cl::desc
Definition: CommandLine.h:413
llvm::wasm::WasmTableType
Definition: Wasm.h:83
llvm::wasm::WASM_TYPE_FUNCREF
@ WASM_TYPE_FUNCREF
Definition: Wasm.h:266
llvm::MachineBasicBlock::end
iterator end()
Definition: MachineBasicBlock.h:307
llvm::WebAssembly::WasmEnableEmEH
cl::opt< bool > WasmEnableEmEH
llvm::MachineOperand::isGlobal
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
Definition: MachineOperand.h:338