LLVM  8.0.1
WebAssemblyMCInstLower.cpp
Go to the documentation of this file.
1 // WebAssemblyMCInstLower.cpp - Convert WebAssembly MachineInstr to an MCInst //
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 contains code to lower WebAssembly MachineInstrs to their
12 /// corresponding MCInst records.
13 ///
14 //===----------------------------------------------------------------------===//
15 
16 #include "WebAssemblyMCInstLower.h"
17 #include "WebAssemblyAsmPrinter.h"
20 #include "WebAssemblyUtilities.h"
23 #include "llvm/IR/Constants.h"
24 #include "llvm/MC/MCAsmInfo.h"
25 #include "llvm/MC/MCContext.h"
26 #include "llvm/MC/MCExpr.h"
27 #include "llvm/MC/MCInst.h"
28 #include "llvm/MC/MCSymbolWasm.h"
31 using namespace llvm;
32 
33 // Defines llvm::WebAssembly::getStackOpcode to convert register instructions to
34 // stack instructions
35 #define GET_INSTRMAP_INFO 1
36 #include "WebAssemblyGenInstrInfo.inc"
37 
38 // This disables the removal of registers when lowering into MC, as required
39 // by some current tests.
40 static cl::opt<bool>
41  WasmKeepRegisters("wasm-keep-registers", cl::Hidden,
42  cl::desc("WebAssembly: output stack registers in"
43  " instruction output for test purposes only."),
44  cl::init(false));
45 
46 static void removeRegisterOperands(const MachineInstr *MI, MCInst &OutMI);
47 
48 MCSymbol *
49 WebAssemblyMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
50  const GlobalValue *Global = MO.getGlobal();
51  MCSymbolWasm *WasmSym = cast<MCSymbolWasm>(Printer.getSymbol(Global));
52 
53  if (const auto *FuncTy = dyn_cast<FunctionType>(Global->getValueType())) {
54  const MachineFunction &MF = *MO.getParent()->getParent()->getParent();
55  const TargetMachine &TM = MF.getTarget();
56  const Function &CurrentFunc = MF.getFunction();
57 
58  SmallVector<MVT, 1> ResultMVTs;
59  SmallVector<MVT, 4> ParamMVTs;
60  ComputeSignatureVTs(FuncTy, CurrentFunc, TM, ParamMVTs, ResultMVTs);
61 
62  auto Signature = SignatureFromMVTs(ResultMVTs, ParamMVTs);
63  WasmSym->setSignature(Signature.get());
64  Printer.addSignature(std::move(Signature));
66  }
67 
68  return WasmSym;
69 }
70 
71 MCSymbol *WebAssemblyMCInstLower::GetExternalSymbolSymbol(
72  const MachineOperand &MO) const {
73  const char *Name = MO.getSymbolName();
74  MCSymbolWasm *WasmSym =
75  cast<MCSymbolWasm>(Printer.GetExternalSymbolSymbol(Name));
76  const WebAssemblySubtarget &Subtarget = Printer.getSubtarget();
77 
78  // Except for the two exceptions (__stack_pointer and __cpp_exception), all
79  // other external symbols used by CodeGen are functions. It's OK to hardcode
80  // knowledge of specific symbols here; this method is precisely there for
81  // fetching the signatures of known Clang-provided symbols.
82  if (strcmp(Name, "__stack_pointer") == 0) {
85  uint8_t(Subtarget.hasAddr64() ? wasm::WASM_TYPE_I64
87  true});
88  return WasmSym;
89  }
90 
93  if (strcmp(Name, "__cpp_exception") == 0) {
95  // We can't confirm its signature index for now because there can be
96  // imported exceptions. Set it to be 0 for now.
97  WasmSym->setEventType(
98  {wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION, /* SigIndex */ 0});
99  // We may have multiple C++ compilation units to be linked together, each of
100  // which defines the exception symbol. To resolve them, we declare them as
101  // weak.
102  WasmSym->setWeak(true);
103  WasmSym->setExternal(true);
104 
105  // All C++ exceptions are assumed to have a single i32 (for wasm32) or i64
106  // (for wasm64) param type and void return type. The reaon is, all C++
107  // exception values are pointers, and to share the type section with
108  // functions, exceptions are assumed to have void return type.
109  Params.push_back(Subtarget.hasAddr64() ? wasm::ValType::I64
111  } else { // Function symbols
113  GetLibcallSignature(Subtarget, Name, Returns, Params);
114  }
115  auto Signature =
116  make_unique<wasm::WasmSignature>(std::move(Returns), std::move(Params));
117  WasmSym->setSignature(Signature.get());
118  Printer.addSignature(std::move(Signature));
119 
120  return WasmSym;
121 }
122 
123 MCOperand WebAssemblyMCInstLower::LowerSymbolOperand(MCSymbol *Sym,
124  int64_t Offset,
125  bool IsFunc, bool IsGlob,
126  bool IsEvent) const {
132 
133  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, VK, Ctx);
134 
135  if (Offset != 0) {
136  if (IsFunc)
137  report_fatal_error("Function addresses with offsets not supported");
138  if (IsGlob)
139  report_fatal_error("Global indexes with offsets not supported");
140  if (IsEvent)
141  report_fatal_error("Event indexes with offsets not supported");
142  Expr =
143  MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, Ctx), Ctx);
144  }
145 
146  return MCOperand::createExpr(Expr);
147 }
148 
149 // Return the WebAssembly type associated with the given register class.
151  if (RC == &WebAssembly::I32RegClass)
152  return wasm::ValType::I32;
153  if (RC == &WebAssembly::I64RegClass)
154  return wasm::ValType::I64;
155  if (RC == &WebAssembly::F32RegClass)
156  return wasm::ValType::F32;
157  if (RC == &WebAssembly::F64RegClass)
158  return wasm::ValType::F64;
159  if (RC == &WebAssembly::V128RegClass)
160  return wasm::ValType::V128;
161  llvm_unreachable("Unexpected register class");
162 }
163 
165  MCInst &OutMI) const {
166  OutMI.setOpcode(MI->getOpcode());
167 
168  const MCInstrDesc &Desc = MI->getDesc();
169  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
170  const MachineOperand &MO = MI->getOperand(i);
171 
172  MCOperand MCOp;
173  switch (MO.getType()) {
174  default:
175  MI->print(errs());
176  llvm_unreachable("unknown operand type");
178  MI->print(errs());
179  llvm_unreachable("MachineBasicBlock operand should have been rewritten");
181  // Ignore all implicit register operands.
182  if (MO.isImplicit())
183  continue;
184  const WebAssemblyFunctionInfo &MFI =
186  unsigned WAReg = MFI.getWAReg(MO.getReg());
187  MCOp = MCOperand::createReg(WAReg);
188  break;
189  }
191  if (i < Desc.NumOperands) {
192  const MCOperandInfo &Info = Desc.OpInfo[i];
194  MCSymbol *Sym = Printer.createTempSymbol("typeindex");
195 
198 
199  const MachineRegisterInfo &MRI =
200  MI->getParent()->getParent()->getRegInfo();
201  for (const MachineOperand &MO : MI->defs())
202  Returns.push_back(getType(MRI.getRegClass(MO.getReg())));
203  for (const MachineOperand &MO : MI->explicit_uses())
204  if (MO.isReg())
205  Params.push_back(getType(MRI.getRegClass(MO.getReg())));
206 
207  // call_indirect instructions have a callee operand at the end which
208  // doesn't count as a param.
210  Params.pop_back();
211 
212  MCSymbolWasm *WasmSym = cast<MCSymbolWasm>(Sym);
213  auto Signature = make_unique<wasm::WasmSignature>(std::move(Returns),
214  std::move(Params));
215  WasmSym->setSignature(Signature.get());
216  Printer.addSignature(std::move(Signature));
218 
219  const MCExpr *Expr = MCSymbolRefExpr::create(
221  MCOp = MCOperand::createExpr(Expr);
222  break;
223  }
224  }
225  MCOp = MCOperand::createImm(MO.getImm());
226  break;
228  // TODO: MC converts all floating point immediate operands to double.
229  // This is fine for numeric values, but may cause NaNs to change bits.
230  const ConstantFP *Imm = MO.getFPImm();
231  if (Imm->getType()->isFloatTy())
233  else if (Imm->getType()->isDoubleTy())
235  else
236  llvm_unreachable("unknown floating point immediate type");
237  break;
238  }
241  "WebAssembly does not use target flags on GlobalAddresses");
242  MCOp = LowerSymbolOperand(GetGlobalAddressSymbol(MO), MO.getOffset(),
244  false, false);
245  break;
247  // The target flag indicates whether this is a symbol for a
248  // variable or a function.
249  assert((MO.getTargetFlags() & ~WebAssemblyII::MO_SYMBOL_MASK) == 0 &&
250  "WebAssembly uses only symbol flags on ExternalSymbols");
251  MCOp = LowerSymbolOperand(
252  GetExternalSymbolSymbol(MO), /*Offset=*/0,
256  break;
258  // This is currently used only for LSDA symbols (GCC_except_table),
259  // because global addresses or other external symbols are handled above.
260  assert(MO.getTargetFlags() == 0 &&
261  "WebAssembly does not use target flags on MCSymbol");
262  MCOp = LowerSymbolOperand(MO.getMCSymbol(), /*Offset=*/0, false, false,
263  false);
264  break;
265  }
266 
267  OutMI.addOperand(MCOp);
268  }
269 
270  if (!WasmKeepRegisters)
271  removeRegisterOperands(MI, OutMI);
272 }
273 
274 static void removeRegisterOperands(const MachineInstr *MI, MCInst &OutMI) {
275  // Remove all uses of stackified registers to bring the instruction format
276  // into its final stack form used thruout MC, and transition opcodes to
277  // their _S variant.
278  // We do this seperate from the above code that still may need these
279  // registers for e.g. call_indirect signatures.
280  // See comments in lib/Target/WebAssembly/WebAssemblyInstrFormats.td for
281  // details.
282  // TODO: the code above creates new registers which are then removed here.
283  // That code could be slightly simplified by not doing that, though maybe
284  // it is simpler conceptually to keep the code above in "register mode"
285  // until this transition point.
286  // FIXME: we are not processing inline assembly, which contains register
287  // operands, because it is used by later target generic code.
288  if (MI->isDebugInstr() || MI->isLabel() || MI->isInlineAsm())
289  return;
290 
291  // Transform to _S instruction.
292  auto RegOpcode = OutMI.getOpcode();
293  auto StackOpcode = WebAssembly::getStackOpcode(RegOpcode);
294  assert(StackOpcode != -1 && "Failed to stackify instruction");
295  OutMI.setOpcode(StackOpcode);
296 
297  // Remove register operands.
298  for (auto I = OutMI.getNumOperands(); I; --I) {
299  auto &MO = OutMI.getOperand(I - 1);
300  if (MO.isReg()) {
301  OutMI.erase(&MO);
302  }
303  }
304 }
unsigned getTargetFlags() const
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
bool isLabel() const
Returns true if the MachineInstr represents a label.
Definition: MachineInstr.h:986
const TargetRegisterClass * getRegClass(unsigned Reg) const
Return the register class of the specified virtual register.
MCSymbol * GetExternalSymbolSymbol(StringRef Sym) const
Return the MCSymbol for the specified ExternalSymbol.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:323
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:140
This class represents lattice values for constants.
Definition: AllocatorList.h:24
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
void setWeak(bool isWeak)
Definition: MCSymbolWasm.h:51
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:137
void push_back(const T &Elt)
Definition: SmallVector.h:218
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:164
unsigned getReg() const
getReg - Returns the register number.
void setGlobalType(wasm::WasmGlobalType GT)
Definition: MCSymbolWasm.h:82
bool isInlineAsm() const
This file declares the class to lower WebAssembly MachineInstrs to their corresponding MCInst records...
float convertToFloat() const
Definition: APFloat.h:1098
MachineBasicBlock reference.
static cl::opt< bool > WasmKeepRegisters("wasm-keep-registers", cl::Hidden, cl::desc("WebAssembly: output stack registers in" " instruction output for test purposes only."), cl::init(false))
amdgpu Simplify well known AMD library false Value Value const Twine & Name
void setExternal(bool Value) const
Definition: MCSymbol.h:394
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:116
const ConstantFP * getFPImm() const
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:412
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:36
void erase(iterator I)
Definition: MCInst.h:192
Name of external global symbol.
static void removeRegisterOperands(const MachineInstr *MI, MCInst &OutMI)
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:409
const char * getSymbolName() const
uint8_t OperandType
Information about the type of the operand.
Definition: MCInstrDesc.h:79
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
Definition: MachineInstr.h:406
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:245
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:461
Analysis containing CSE Info
Definition: CSEInfo.cpp:21
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:161
void setEventType(wasm::WasmEventType ET)
Definition: MCSymbolWasm.h:88
unsigned short NumOperands
Definition: MCInstrDesc.h:167
This file contains the declaration of the WebAssembly-specific utility functions. ...
bool isFloatTy() const
Return true if this is &#39;float&#39;, a 32-bit IEEE fp type.
Definition: Type.h:147
Address of a global value.
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:423
unsigned const MachineRegisterInfo * MRI
This file provides signature information for runtime libcalls.
const WebAssemblySubtarget & getSubtarget() const
This file contains the declarations for the subclasses of Constant, which represent the different fla...
const GlobalValue * getGlobal() const
ConstantFP - Floating Point Values [float, double].
Definition: Constants.h:264
double convertToDouble() const
Definition: APFloat.h:1097
iterator_range< mop_iterator > defs()
Returns a range over all explicit operands that are register definitions.
Definition: MachineInstr.h:481
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
std::unique_ptr< wasm::WasmSignature > SignatureFromMVTs(const SmallVectorImpl< MVT > &Results, const SmallVectorImpl< MVT > &Params)
unsigned getNumOperands() const
Definition: MCInst.h:184
void print(raw_ostream &OS, bool IsStandalone=true, bool SkipOpers=false, bool SkipDebugLoc=false, bool AddNewLine=true, const TargetInstrInfo *TII=nullptr) const
Print this MI to OS.
type signature immediate for call_indirect.
static wasm::ValType getType(const TargetRegisterClass *RC)
bool isDebugInstr() const
Definition: MachineInstr.h:999
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void setType(wasm::WasmSymbolType type)
Definition: MCSymbolWasm.h:48
iterator_range< mop_iterator > explicit_uses()
Definition: MachineInstr.h:499
void addSignature(std::unique_ptr< wasm::WasmSignature > &&Sig)
const APFloat & getValueAPF() const
Definition: Constants.h:303
void Lower(const MachineInstr *MI, MCInst &OutMI) const
void GetLibcallSignature(const WebAssemblySubtarget &Subtarget, RTLIB::Libcall LC, SmallVectorImpl< wasm::ValType > &Rets, SmallVectorImpl< wasm::ValType > &Params)
void setOpcode(unsigned Op)
Definition: MCInst.h:173
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:430
MachineOperand class - Representation of each machine instruction operand.
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:182
static MCOperand createFPImm(double Val)
Definition: MCInst.h:130
int64_t getImm() const
const Function & getFunction() const
Return the LLVM function that this machine code represents.
MCSymbol reference (for debug/eh info)
void ComputeSignatureVTs(const FunctionType *Ty, const Function &F, const TargetMachine &TM, SmallVectorImpl< MVT > &Params, SmallVectorImpl< MVT > &Results)
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:254
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
Representation of each machine instruction.
Definition: MachineInstr.h:64
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
bool isFunctionTy() const
True if this is an instance of FunctionType.
Definition: Type.h:215
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
int64_t getOffset() const
Return the offset from the symbol in this operand.
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares WebAssembly-specific per-machine-function information.
Type * getValueType() const
Definition: GlobalValue.h:276
unsigned getWAReg(unsigned VReg) const
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
bool isReg() const
isReg - Tests if this is a MO_Register operand.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
void setSignature(wasm::WasmSignature *Sig)
Definition: MCSymbolWasm.h:76
MCSymbol * getMCSymbol() const
Floating-point immediate operand.
const MCOperandInfo * OpInfo
Definition: MCInstrDesc.h:175
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:59
IRTranslator LLVM IR MI
void addOperand(const MCOperand &Op)
Definition: MCInst.h:186
bool isCallIndirect(const MachineInstr &MI)
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition: MCInstrDesc.h:67
unsigned getOpcode() const
Definition: MCInst.h:174
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:414
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:35
bool isDoubleTy() const
Return true if this is &#39;double&#39;, a 64-bit IEEE fp type.
Definition: Type.h:150
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
MCSymbol * createTempSymbol(const Twine &Name) const
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:123
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx)
Definition: MCExpr.cpp:164
bool isImplicit() const