WebAssemblyMCInstLower.cpp revision 292941
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 "WebAssemblyMachineFunctionInfo.h"
18#include "llvm/CodeGen/AsmPrinter.h"
19#include "llvm/CodeGen/MachineFunction.h"
20#include "llvm/IR/Constants.h"
21#include "llvm/MC/MCAsmInfo.h"
22#include "llvm/MC/MCContext.h"
23#include "llvm/MC/MCExpr.h"
24#include "llvm/MC/MCInst.h"
25#include "llvm/Support/ErrorHandling.h"
26#include "llvm/Support/raw_ostream.h"
27using namespace llvm;
28
29MCSymbol *
30WebAssemblyMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
31  return Printer.getSymbol(MO.getGlobal());
32}
33
34MCSymbol *WebAssemblyMCInstLower::GetExternalSymbolSymbol(
35    const MachineOperand &MO) const {
36  return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
37}
38
39MCOperand WebAssemblyMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
40                                                     MCSymbol *Sym) const {
41  assert(MO.getTargetFlags() == 0 && "WebAssembly does not use target flags");
42
43  const MCExpr *Expr = MCSymbolRefExpr::create(Sym, Ctx);
44
45  int64_t Offset = MO.getOffset();
46  if (Offset != 0) {
47    assert(!MO.isJTI() && "Unexpected offset with jump table index");
48    Expr =
49        MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, Ctx), Ctx);
50  }
51
52  return MCOperand::createExpr(Expr);
53}
54
55void WebAssemblyMCInstLower::Lower(const MachineInstr *MI,
56                                   MCInst &OutMI) const {
57  OutMI.setOpcode(MI->getOpcode());
58
59  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
60    const MachineOperand &MO = MI->getOperand(i);
61
62    MCOperand MCOp;
63    switch (MO.getType()) {
64    default:
65      MI->dump();
66      llvm_unreachable("unknown operand type");
67    case MachineOperand::MO_Register: {
68      // Ignore all implicit register operands.
69      if (MO.isImplicit())
70        continue;
71      const WebAssemblyFunctionInfo &MFI =
72          *MI->getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>();
73      unsigned WAReg = MFI.getWAReg(MO.getReg());
74      MCOp = MCOperand::createReg(WAReg);
75      break;
76    }
77    case MachineOperand::MO_Immediate:
78      MCOp = MCOperand::createImm(MO.getImm());
79      break;
80    case MachineOperand::MO_FPImmediate: {
81      // TODO: MC converts all floating point immediate operands to double.
82      // This is fine for numeric values, but may cause NaNs to change bits.
83      const ConstantFP *Imm = MO.getFPImm();
84      if (Imm->getType()->isFloatTy())
85        MCOp = MCOperand::createFPImm(Imm->getValueAPF().convertToFloat());
86      else if (Imm->getType()->isDoubleTy())
87        MCOp = MCOperand::createFPImm(Imm->getValueAPF().convertToDouble());
88      else
89        llvm_unreachable("unknown floating point immediate type");
90      break;
91    }
92    case MachineOperand::MO_MachineBasicBlock:
93      MCOp = MCOperand::createExpr(
94          MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx));
95      break;
96    case MachineOperand::MO_GlobalAddress:
97      MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
98      break;
99    case MachineOperand::MO_ExternalSymbol:
100      MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
101      break;
102    }
103
104    OutMI.addOperand(MCOp);
105  }
106}
107