LLVM  14.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 const char *const WebAssembly::CxaBeginCatchFn = "__cxa_begin_catch";
22 const char *const WebAssembly::CxaRethrowFn = "__cxa_rethrow";
23 const char *const WebAssembly::StdTerminateFn = "_ZSt9terminatev";
25  "_Unwind_Wasm_CallPersonality";
26 
27 /// Test whether MI is a child of some other node in an expression tree.
29  const WebAssemblyFunctionInfo &MFI) {
30  if (MI.getNumOperands() == 0)
31  return false;
32  const MachineOperand &MO = MI.getOperand(0);
33  if (!MO.isReg() || MO.isImplicit() || !MO.isDef())
34  return false;
35  Register Reg = MO.getReg();
37 }
38 
40  switch (MI.getOpcode()) {
41  case WebAssembly::THROW:
42  case WebAssembly::THROW_S:
43  case WebAssembly::RETHROW:
44  case WebAssembly::RETHROW_S:
45  return true;
46  }
47  if (isCallIndirect(MI.getOpcode()))
48  return true;
49  if (!MI.isCall())
50  return false;
51 
52  const MachineOperand &MO = getCalleeOp(MI);
53  assert(MO.isGlobal() || MO.isSymbol());
54 
55  if (MO.isSymbol()) {
56  // Some intrinsics are lowered to calls to external symbols, which are then
57  // lowered to calls to library functions. Most of libcalls don't throw, but
58  // we only list some of them here now.
59  // TODO Consider adding 'nounwind' info in TargetLowering::CallLoweringInfo
60  // instead for more accurate info.
61  const char *Name = MO.getSymbolName();
62  if (strcmp(Name, "memcpy") == 0 || strcmp(Name, "memmove") == 0 ||
63  strcmp(Name, "memset") == 0)
64  return false;
65  return true;
66  }
67 
68  const auto *F = dyn_cast<Function>(MO.getGlobal());
69  if (!F)
70  return true;
71  if (F->doesNotThrow())
72  return false;
73  // These functions never throw
74  if (F->getName() == CxaBeginCatchFn || F->getName() == PersonalityWrapperFn ||
75  F->getName() == StdTerminateFn)
76  return false;
77 
78  // TODO Can we exclude call instructions that are marked as 'nounwind' in the
79  // original LLVm IR? (Even when the callee may throw)
80  return true;
81 }
82 
84  switch (MI.getOpcode()) {
85  case WebAssembly::CALL:
86  case WebAssembly::CALL_S:
87  case WebAssembly::RET_CALL:
88  case WebAssembly::RET_CALL_S:
89  return MI.getOperand(MI.getNumExplicitDefs());
90  case WebAssembly::CALL_INDIRECT:
91  case WebAssembly::CALL_INDIRECT_S:
92  case WebAssembly::RET_CALL_INDIRECT:
93  case WebAssembly::RET_CALL_INDIRECT_S:
94  return MI.getOperand(MI.getNumExplicitOperands() - 1);
95  default:
96  llvm_unreachable("Not a call instruction");
97  }
98 }
99 
101  MCContext &Ctx, const WebAssemblySubtarget *Subtarget) {
102  StringRef Name = "__indirect_function_table";
103  MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(Name));
104  if (Sym) {
105  if (!Sym->isFunctionTable())
106  Ctx.reportError(SMLoc(), "symbol is not a wasm funcref table");
107  } else {
108  Sym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(Name));
109  Sym->setFunctionTable();
110  // The default function table is synthesized by the linker.
111  Sym->setUndefined();
112  }
113  // MVP object files can't have symtab entries for tables.
114  if (!(Subtarget && Subtarget->hasReferenceTypes()))
116  return Sym;
117 }
118 
120  MCContext &Ctx, const WebAssemblySubtarget *Subtarget) {
121  StringRef Name = "__funcref_call_table";
122  MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(Name));
123  if (Sym) {
124  if (!Sym->isFunctionTable())
125  Ctx.reportError(SMLoc(), "symbol is not a wasm funcref table");
126  } else {
127  Sym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(Name));
128 
129  // Setting Weak ensure only one table is left after linking when multiple
130  // modules define the table.
131  Sym->setWeak(true);
132 
133  wasm::WasmLimits Limits = {0, 1, 1};
134  wasm::WasmTableType TableType = {wasm::WASM_TYPE_FUNCREF, Limits};
136  Sym->setTableType(TableType);
137  }
138  // MVP object files can't have symtab entries for tables.
139  if (!(Subtarget && Subtarget->hasReferenceTypes()))
141  return Sym;
142 }
143 
144 // Find a catch instruction from an EH pad.
146  assert(EHPad->isEHPad());
147  auto Pos = EHPad->begin();
148  // Skip any label or debug instructions. Also skip 'end' marker instructions
149  // that may exist after marker placement in CFGStackify.
150  while (Pos != EHPad->end() &&
151  (Pos->isLabel() || Pos->isDebugInstr() || isMarker(Pos->getOpcode())))
152  Pos++;
153  if (Pos != EHPad->end() && WebAssembly::isCatch(Pos->getOpcode()))
154  return &*Pos;
155  return nullptr;
156 }
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:28
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:83
MI
IRTranslator LLVM IR MI
Definition: IRTranslator.cpp:105
MachineInstr.h
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
Reg
unsigned Reg
Definition: MachineSink.cpp:1558
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:145
llvm::MachineOperand::getGlobal
const GlobalValue * getGlobal() const
Definition: MachineOperand.h:563
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:72
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:100
llvm::wasm::WASM_SYMBOL_TYPE_TABLE
@ WASM_SYMBOL_TYPE_TABLE
Definition: Wasm.h:375
llvm::WebAssembly::mayThrow
bool mayThrow(const MachineInstr &MI)
Definition: WebAssemblyUtilities.cpp:39
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:341
llvm::AArch64ISD::CALL
@ CALL
Definition: AArch64ISelLowering.h:52
llvm::WebAssembly::isMarker
bool isMarker(unsigned Opc)
Definition: WebAssemblyMCTargetDesc.h:387
llvm::wasm::WASM_TYPE_FUNCREF
@ WASM_TYPE_FUNCREF
Definition: Wasm.h:258
llvm::MCContext::lookupSymbol
MCSymbol * lookupSymbol(const Twine &Name) const
Get the symbol for Name, or null.
Definition: MCContext.cpp:344
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::MCContext::getOrCreateSymbol
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:191
llvm::MachineOperand::isImplicit
bool isImplicit() const
Definition: MachineOperand.h:380
MachineLoopInfo.h
llvm::SMLoc
Represents a location in source code.
Definition: SMLoc.h:23
llvm::wasm::WasmLimits
Definition: Wasm.h:77
MCContext.h
llvm::MachineOperand
MachineOperand class - Representation of each machine instruction operand.
Definition: MachineOperand.h:49
llvm::MCSymbolWasm::setType
void setType(wasm::WasmSymbolType type)
Definition: MCSymbolWasm.h:53
llvm::WebAssembly::StdTerminateFn
const char *const StdTerminateFn
Definition: WebAssemblyUtilities.cpp:23
llvm::MachineBasicBlock
Definition: MachineBasicBlock.h:95
WebAssemblyUtilities.h
llvm::WebAssembly::CxaBeginCatchFn
const char *const CxaBeginCatchFn
Definition: WebAssemblyUtilities.cpp:21
llvm::WebAssemblySubtarget::hasReferenceTypes
bool hasReferenceTypes() const
Definition: WebAssemblySubtarget.h:102
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:321
llvm::MachineInstr
Representation of each machine instruction.
Definition: MachineInstr.h:64
llvm::MCSymbolWasm
Definition: MCSymbolWasm.h:16
llvm::WebAssembly::CxaRethrowFn
const char *const CxaRethrowFn
Definition: WebAssemblyUtilities.cpp:22
llvm::MCSymbolWasm::setWeak
void setWeak(bool isWeak)
Definition: MCSymbolWasm.h:75
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:136
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:963
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:360
WebAssemblyMachineFunctionInfo.h
llvm::MachineBasicBlock::isEHPad
bool isEHPad() const
Returns true if the block is a landing pad.
Definition: MachineBasicBlock.h:526
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
llvm::MachineOperand::isDef
bool isDef() const
Definition: MachineOperand.h:375
llvm::WebAssemblySubtarget
Definition: WebAssemblySubtarget.h:35
llvm::WebAssembly::PersonalityWrapperFn
const char *const PersonalityWrapperFn
Definition: WebAssemblyUtilities.cpp:24
llvm::Register
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
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:119
llvm::MCSymbolWasm::setFunctionTable
void setFunctionTable()
Definition: MCSymbolWasm.h:117
llvm::MachineBasicBlock::begin
iterator begin()
Definition: MachineBasicBlock.h:268
llvm::MachineOperand::getSymbolName
const char * getSymbolName() const
Definition: MachineOperand.h:608
llvm::wasm::WasmTableType
Definition: Wasm.h:83
llvm::MachineBasicBlock::end
iterator end()
Definition: MachineBasicBlock.h:270
llvm::MachineOperand::isGlobal
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
Definition: MachineOperand.h:339