WebAssemblyMCInstLower.cpp revision 294024
1292915Sdim// WebAssemblyMCInstLower.cpp - Convert WebAssembly MachineInstr to an MCInst // 2292915Sdim// 3292915Sdim// The LLVM Compiler Infrastructure 4292915Sdim// 5292915Sdim// This file is distributed under the University of Illinois Open Source 6292915Sdim// License. See LICENSE.TXT for details. 7292915Sdim// 8292915Sdim//===----------------------------------------------------------------------===// 9292915Sdim/// 10292915Sdim/// \file 11292915Sdim/// \brief This file contains code to lower WebAssembly MachineInstrs to their 12292915Sdim/// corresponding MCInst records. 13292915Sdim/// 14292915Sdim//===----------------------------------------------------------------------===// 15292915Sdim 16292915Sdim#include "WebAssemblyMCInstLower.h" 17292915Sdim#include "WebAssemblyMachineFunctionInfo.h" 18292915Sdim#include "llvm/CodeGen/AsmPrinter.h" 19292915Sdim#include "llvm/CodeGen/MachineFunction.h" 20292915Sdim#include "llvm/IR/Constants.h" 21292915Sdim#include "llvm/MC/MCAsmInfo.h" 22292915Sdim#include "llvm/MC/MCContext.h" 23292915Sdim#include "llvm/MC/MCExpr.h" 24292915Sdim#include "llvm/MC/MCInst.h" 25292915Sdim#include "llvm/Support/ErrorHandling.h" 26292915Sdim#include "llvm/Support/raw_ostream.h" 27292915Sdimusing namespace llvm; 28292915Sdim 29292915SdimMCSymbol * 30292915SdimWebAssemblyMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const { 31292915Sdim return Printer.getSymbol(MO.getGlobal()); 32292915Sdim} 33292915Sdim 34292915SdimMCSymbol *WebAssemblyMCInstLower::GetExternalSymbolSymbol( 35292915Sdim const MachineOperand &MO) const { 36292915Sdim return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); 37292915Sdim} 38292915Sdim 39294024SdimMCOperand WebAssemblyMCInstLower::LowerSymbolOperand(MCSymbol *Sym, 40294024Sdim int64_t Offset, 41294024Sdim bool IsFunc) const { 42294024Sdim MCSymbolRefExpr::VariantKind VK = 43294024Sdim IsFunc ? MCSymbolRefExpr::VK_WebAssembly_FUNCTION 44294024Sdim : MCSymbolRefExpr::VK_None; 45294024Sdim const MCExpr *Expr = MCSymbolRefExpr::create(Sym, VK, Ctx); 46292915Sdim 47292915Sdim if (Offset != 0) { 48294024Sdim if (IsFunc) 49294024Sdim report_fatal_error("Function addresses with offsets not supported"); 50292915Sdim Expr = 51292915Sdim MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, Ctx), Ctx); 52292915Sdim } 53292915Sdim 54292915Sdim return MCOperand::createExpr(Expr); 55292915Sdim} 56292915Sdim 57292915Sdimvoid WebAssemblyMCInstLower::Lower(const MachineInstr *MI, 58292915Sdim MCInst &OutMI) const { 59292915Sdim OutMI.setOpcode(MI->getOpcode()); 60292915Sdim 61292915Sdim for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 62292915Sdim const MachineOperand &MO = MI->getOperand(i); 63292915Sdim 64292915Sdim MCOperand MCOp; 65292915Sdim switch (MO.getType()) { 66292915Sdim default: 67292915Sdim MI->dump(); 68292915Sdim llvm_unreachable("unknown operand type"); 69294024Sdim case MachineOperand::MO_MachineBasicBlock: 70294024Sdim MI->dump(); 71294024Sdim llvm_unreachable("MachineBasicBlock operand should have been rewritten"); 72292915Sdim case MachineOperand::MO_Register: { 73292915Sdim // Ignore all implicit register operands. 74292915Sdim if (MO.isImplicit()) 75292915Sdim continue; 76292915Sdim const WebAssemblyFunctionInfo &MFI = 77292915Sdim *MI->getParent()->getParent()->getInfo<WebAssemblyFunctionInfo>(); 78292915Sdim unsigned WAReg = MFI.getWAReg(MO.getReg()); 79292915Sdim MCOp = MCOperand::createReg(WAReg); 80292915Sdim break; 81292915Sdim } 82292915Sdim case MachineOperand::MO_Immediate: 83292915Sdim MCOp = MCOperand::createImm(MO.getImm()); 84292915Sdim break; 85292915Sdim case MachineOperand::MO_FPImmediate: { 86292915Sdim // TODO: MC converts all floating point immediate operands to double. 87292915Sdim // This is fine for numeric values, but may cause NaNs to change bits. 88292915Sdim const ConstantFP *Imm = MO.getFPImm(); 89292915Sdim if (Imm->getType()->isFloatTy()) 90292915Sdim MCOp = MCOperand::createFPImm(Imm->getValueAPF().convertToFloat()); 91292915Sdim else if (Imm->getType()->isDoubleTy()) 92292915Sdim MCOp = MCOperand::createFPImm(Imm->getValueAPF().convertToDouble()); 93292915Sdim else 94292915Sdim llvm_unreachable("unknown floating point immediate type"); 95292915Sdim break; 96292915Sdim } 97292915Sdim case MachineOperand::MO_GlobalAddress: 98294024Sdim assert(MO.getTargetFlags() == 0 && 99294024Sdim "WebAssembly does not use target flags on GlobalAddresses"); 100294024Sdim MCOp = LowerSymbolOperand(GetGlobalAddressSymbol(MO), MO.getOffset(), 101294024Sdim MO.getGlobal()->getValueType()->isFunctionTy()); 102292915Sdim break; 103292915Sdim case MachineOperand::MO_ExternalSymbol: 104294024Sdim // The target flag indicates whether this is a symbol for a 105294024Sdim // variable or a function. 106294024Sdim assert((MO.getTargetFlags() & -2) == 0 && 107294024Sdim "WebAssembly uses only one target flag bit on ExternalSymbols"); 108294024Sdim MCOp = LowerSymbolOperand(GetExternalSymbolSymbol(MO), /*Offset=*/0, 109294024Sdim MO.getTargetFlags() & 1); 110292915Sdim break; 111292915Sdim } 112292915Sdim 113292915Sdim OutMI.addOperand(MCOp); 114292915Sdim } 115292915Sdim} 116