LLVM  6.0.0svn
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 /// \brief 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/MCSymbolELF.h"
29 #include "llvm/MC/MCSymbolWasm.h"
32 using namespace llvm;
33 
34 MCSymbol *
35 WebAssemblyMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
36  const GlobalValue *Global = MO.getGlobal();
37  MCSymbol *Sym = Printer.getSymbol(Global);
38  if (isa<MCSymbolELF>(Sym))
39  return Sym;
40 
41  MCSymbolWasm *WasmSym = cast<MCSymbolWasm>(Sym);
42 
43  if (const auto *FuncTy = dyn_cast<FunctionType>(Global->getValueType())) {
44  const MachineFunction &MF = *MO.getParent()->getParent()->getParent();
45  const TargetMachine &TM = MF.getTarget();
46  const Function &CurrentFunc = *MF.getFunction();
47 
50 
51  wasm::ValType iPTR =
52  MF.getSubtarget<WebAssemblySubtarget>().hasAddr64() ?
55 
56  SmallVector<MVT, 4> ResultMVTs;
57  ComputeLegalValueVTs(CurrentFunc, TM, FuncTy->getReturnType(), ResultMVTs);
58  // WebAssembly can't currently handle returning tuples.
59  if (ResultMVTs.size() <= 1)
60  for (MVT ResultMVT : ResultMVTs)
61  Returns.push_back(WebAssembly::toValType(ResultMVT));
62  else
63  Params.push_back(iPTR);
64 
65  for (Type *Ty : FuncTy->params()) {
66  SmallVector<MVT, 4> ParamMVTs;
67  ComputeLegalValueVTs(CurrentFunc, TM, Ty, ParamMVTs);
68  for (MVT ParamMVT : ParamMVTs)
69  Params.push_back(WebAssembly::toValType(ParamMVT));
70  }
71 
72  if (FuncTy->isVarArg())
73  Params.push_back(iPTR);
74 
75  WasmSym->setReturns(std::move(Returns));
76  WasmSym->setParams(std::move(Params));
77  WasmSym->setIsFunction(true);
78  }
79 
80  return WasmSym;
81 }
82 
83 MCSymbol *WebAssemblyMCInstLower::GetExternalSymbolSymbol(
84  const MachineOperand &MO) const {
85  const char *Name = MO.getSymbolName();
86  MCSymbol *Sym = Printer.GetExternalSymbolSymbol(Name);
87  if (isa<MCSymbolELF>(Sym))
88  return Sym;
89 
90  MCSymbolWasm *WasmSym = cast<MCSymbolWasm>(Sym);
91  const WebAssemblySubtarget &Subtarget = Printer.getSubtarget();
92 
93  // __stack_pointer is a global variable; all other external symbols used by
94  // CodeGen are functions.
95  if (strcmp(Name, "__stack_pointer") == 0)
96  return WasmSym;
97 
100  GetSignature(Subtarget, Name, Returns, Params);
101 
102  WasmSym->setReturns(std::move(Returns));
103  WasmSym->setParams(std::move(Params));
104  WasmSym->setIsFunction(true);
105 
106  return WasmSym;
107 }
108 
109 MCOperand WebAssemblyMCInstLower::LowerSymbolOperand(MCSymbol *Sym,
110  int64_t Offset,
111  bool IsFunc) const {
115 
116  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, VK, Ctx);
117 
118  if (Offset != 0) {
119  if (IsFunc)
120  report_fatal_error("Function addresses with offsets not supported");
121  Expr =
122  MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, Ctx), Ctx);
123  }
124 
125  return MCOperand::createExpr(Expr);
126 }
127 
128 // Return the WebAssembly type associated with the given register class.
130  if (RC == &WebAssembly::I32RegClass)
131  return wasm::ValType::I32;
132  if (RC == &WebAssembly::I64RegClass)
133  return wasm::ValType::I64;
134  if (RC == &WebAssembly::F32RegClass)
135  return wasm::ValType::F32;
136  if (RC == &WebAssembly::F64RegClass)
137  return wasm::ValType::F64;
138  llvm_unreachable("Unexpected register class");
139 }
140 
142  MCInst &OutMI) const {
143  OutMI.setOpcode(MI->getOpcode());
144 
145  const MCInstrDesc &Desc = MI->getDesc();
146  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
147  const MachineOperand &MO = MI->getOperand(i);
148 
149  MCOperand MCOp;
150  switch (MO.getType()) {
151  default:
152  MI->print(errs());
153  llvm_unreachable("unknown operand type");
155  MI->print(errs());
156  llvm_unreachable("MachineBasicBlock operand should have been rewritten");
158  // Ignore all implicit register operands.
159  if (MO.isImplicit())
160  continue;
161  const WebAssemblyFunctionInfo &MFI =
163  unsigned WAReg = MFI.getWAReg(MO.getReg());
164  MCOp = MCOperand::createReg(WAReg);
165  break;
166  }
168  if (i < Desc.NumOperands) {
169  const MCOperandInfo &Info = Desc.OpInfo[i];
171  MCSymbol *Sym = Printer.createTempSymbol("typeindex");
172  if (!isa<MCSymbolELF>(Sym)) {
175 
176  const MachineRegisterInfo &MRI =
177  MI->getParent()->getParent()->getRegInfo();
178  for (const MachineOperand &MO : MI->defs())
179  Returns.push_back(getType(MRI.getRegClass(MO.getReg())));
180  for (const MachineOperand &MO : MI->explicit_uses())
181  if (MO.isReg())
182  Params.push_back(getType(MRI.getRegClass(MO.getReg())));
183 
184  // call_indirect instructions have a callee operand at the end which
185  // doesn't count as a param.
187  Params.pop_back();
188 
189  MCSymbolWasm *WasmSym = cast<MCSymbolWasm>(Sym);
190  WasmSym->setReturns(std::move(Returns));
191  WasmSym->setParams(std::move(Params));
192  WasmSym->setIsFunction(true);
193 
194  const MCExpr *Expr =
195  MCSymbolRefExpr::create(WasmSym,
197  Ctx);
198  MCOp = MCOperand::createExpr(Expr);
199  break;
200  }
201  }
202  }
203  MCOp = MCOperand::createImm(MO.getImm());
204  break;
206  // TODO: MC converts all floating point immediate operands to double.
207  // This is fine for numeric values, but may cause NaNs to change bits.
208  const ConstantFP *Imm = MO.getFPImm();
209  if (Imm->getType()->isFloatTy())
211  else if (Imm->getType()->isDoubleTy())
213  else
214  llvm_unreachable("unknown floating point immediate type");
215  break;
216  }
218  assert(MO.getTargetFlags() == 0 &&
219  "WebAssembly does not use target flags on GlobalAddresses");
220  MCOp = LowerSymbolOperand(GetGlobalAddressSymbol(MO), MO.getOffset(),
221  MO.getGlobal()->getValueType()->isFunctionTy());
222  break;
224  // The target flag indicates whether this is a symbol for a
225  // variable or a function.
226  assert((MO.getTargetFlags() & -2) == 0 &&
227  "WebAssembly uses only one target flag bit on ExternalSymbols");
228  MCOp = LowerSymbolOperand(GetExternalSymbolSymbol(MO), /*Offset=*/0,
229  MO.getTargetFlags() & 1);
230  break;
231  }
232 
233  OutMI.addOperand(MCOp);
234  }
235 }
unsigned getTargetFlags() const
void push_back(const T &Elt)
Definition: SmallVector.h:212
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.
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:305
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:115
Compute iterated dominance frontiers using a linear time algorithm.
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
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
Definition: SmallVector.h:136
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:137
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:163
unsigned getReg() const
getReg - Returns the register number.
This file declares the class to lower WebAssembly MachineInstrs to their corresponding MCInst records...
float convertToFloat() const
Definition: APFloat.h:1098
void setParams(SmallVectorImpl< wasm::ValType > &&Pars)
Definition: MCSymbolWasm.h:65
MachineBasicBlock reference.
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:116
const ConstantFP * getFPImm() const
unsigned getNumOperands() const
Access to explicit operands of the instruction.
Definition: MachineInstr.h:293
void ComputeLegalValueVTs(const Function &F, const TargetMachine &TM, Type *Ty, SmallVectorImpl< MVT > &ValueVTs)
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:36
Name of external global symbol.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:290
const char * getSymbolName() const
uint8_t OperandType
Information about the type of the operand.
Definition: MCInstrDesc.h:82
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
Definition: MachineInstr.h:287
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:443
wasm::ValType toValType(const MVT &Ty)
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:159
unsigned short NumOperands
Definition: MCInstrDesc.h:166
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.
unsigned const MachineRegisterInfo * MRI
Machine Value Type.
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:46
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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
void setReturns(SmallVectorImpl< wasm::ValType > &&Rets)
Definition: MCSymbolWasm.h:55
iterator_range< mop_iterator > defs()
Returns a range over all explicit operands that are register definitions.
Definition: MachineInstr.h:354
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
type signature immediate for call_indirect.
static wasm::ValType getType(const TargetRegisterClass *RC)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
iterator_range< mop_iterator > explicit_uses()
Definition: MachineInstr.h:374
const APFloat & getValueAPF() const
Definition: Constants.h:294
void setIsFunction(bool isFunc)
Definition: MCSymbolWasm.h:43
void Lower(const MachineInstr *MI, MCInst &OutMI) const
void setOpcode(unsigned Op)
Definition: MCInst.h:171
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:433
MachineOperand class - Representation of each machine instruction operand.
static MCOperand createFPImm(double Val)
Definition: MCInst.h:130
int64_t getImm() const
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:139
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:59
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:212
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
int64_t getOffset() const
Return the offset from the symbol in this operand.
This file declares WebAssembly-specific per-machine-function information.
Type * getValueType() const
Definition: GlobalValue.h:267
void print(raw_ostream &OS, bool SkipOpers=false, bool SkipDebugLoc=false, const TargetInstrInfo *TII=nullptr) const
Debugging supportPrint this MI to OS.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Floating-point immediate operand.
const MCOperandInfo * OpInfo
Definition: MCInstrDesc.h:174
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:57
IRTranslator LLVM IR MI
void addOperand(const MCOperand &Op)
Definition: MCInst.h:184
void GetSignature(const WebAssemblySubtarget &Subtarget, RTLIB::Libcall LC, SmallVectorImpl< wasm::ValType > &Rets, SmallVectorImpl< wasm::ValType > &Params)
bool isCallIndirect(const MachineInstr &MI)
This holds information about one operand of a machine instruction, indicating the register class for ...
Definition: MCInstrDesc.h:70
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:295
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:159
bool isImplicit() const