ARMMCInstLower.cpp revision 637d89fe0eca4fa2b9c95f6c15eb69a99bae83bc
1//===-- ARMMCInstLower.cpp - Convert ARM 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// This file contains code to lower ARM MachineInstrs to their corresponding 11// MCInst records. 12// 13//===----------------------------------------------------------------------===// 14 15#include "ARM.h" 16#include "ARMMCInstLower.h" 17#include "llvm/CodeGen/AsmPrinter.h" 18#include "llvm/Constants.h" 19#include "llvm/CodeGen/MachineBasicBlock.h" 20#include "llvm/MC/MCAsmInfo.h" 21#include "llvm/MC/MCContext.h" 22#include "llvm/MC/MCExpr.h" 23#include "llvm/MC/MCInst.h" 24#include "llvm/Target/Mangler.h" 25#include "llvm/Support/raw_ostream.h" 26#include "llvm/ADT/SmallString.h" 27using namespace llvm; 28 29MCSymbol *ARMMCInstLower::GetGlobalAddressSymbol(const GlobalValue *GV) const { 30 return Printer.Mang->getSymbol(GV); 31} 32 33const MCSymbolRefExpr *ARMMCInstLower:: 34GetSymbolRef(const MachineOperand &MO) const { 35 assert(MO.isGlobal() && "Isn't a global address reference?"); 36 37 const MCSymbolRefExpr *SymRef; 38 const MCSymbol *Symbol = GetGlobalAddressSymbol(MO.getGlobal()); 39 40 switch (MO.getTargetFlags()) { 41 default: assert(0 && "Unknown target flag on GV operand"); 42 case 0: 43 SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx); 44 break; 45 case ARMII::MO_LO16: 46 SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_LO16, Ctx); 47 break; 48 case ARMII::MO_HI16: 49 SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_HI16, Ctx); 50 break; 51 case ARMII::MO_PLT: 52 SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_PLT, Ctx); 53 break; 54 } 55 56 return SymRef; 57} 58 59const MCSymbolRefExpr *ARMMCInstLower:: 60GetExternalSymbolSymbol(const MachineOperand &MO) const { 61 const MCSymbolRefExpr *SymRef; 62 const MCSymbol *Symbol = Printer.GetExternalSymbolSymbol(MO.getSymbolName()); 63 64 switch (MO.getTargetFlags()) { 65 default: assert(0 && "Unknown target flag on external symbol operand"); 66 case 0: 67 SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx); 68 break; 69 case ARMII::MO_LO16: 70 SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_LO16, Ctx); 71 break; 72 case ARMII::MO_HI16: 73 SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_HI16, Ctx); 74 break; 75 case ARMII::MO_PLT: 76 SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_PLT, Ctx); 77 break; 78 } 79 80 return SymRef; 81} 82 83 84 85MCSymbol *ARMMCInstLower:: 86GetJumpTableSymbol(const MachineOperand &MO) const { 87 SmallString<256> Name; 88 raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "JTI" 89 << Printer.getFunctionNumber() << '_' << MO.getIndex(); 90 91 switch (MO.getTargetFlags()) { 92 default: assert(0 && "Unknown target flag on jump table operand"); 93 case 0: break; 94 } 95 96 // Create a symbol for the name. 97 return Ctx.GetOrCreateSymbol(Name.str()); 98} 99 100MCSymbol *ARMMCInstLower:: 101GetConstantPoolIndexSymbol(const MachineOperand &MO) const { 102 SmallString<256> Name; 103 raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "CPI" 104 << Printer.getFunctionNumber() << '_' << MO.getIndex(); 105 106 switch (MO.getTargetFlags()) { 107 default: assert(0 && "Unknown target flag on CPI operand"); 108 case 0: break; 109 } 110 111 // Create a symbol for the name. 112 return Ctx.GetOrCreateSymbol(Name.str()); 113} 114 115MCOperand ARMMCInstLower:: 116LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const { 117 // FIXME: We would like an efficient form for this, so we don't have to do a 118 // lot of extra uniquing. 119 const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx); 120 121 switch (MO.getTargetFlags()) { 122 default: assert(0 && "Unknown target flag on Symbol operand"); 123 case 0: break; 124 } 125 126 if (!MO.isJTI() && MO.getOffset()) 127 Expr = MCBinaryExpr::CreateAdd(Expr, 128 MCConstantExpr::Create(MO.getOffset(), Ctx), 129 Ctx); 130 return MCOperand::CreateExpr(Expr); 131} 132 133MCOperand ARMMCInstLower:: 134LowerSymbolRefOperand(const MachineOperand &MO, 135 const MCSymbolRefExpr *Sym) const { 136 const MCExpr *Expr = Sym; 137 if (!MO.isJTI() && MO.getOffset()) 138 Expr = MCBinaryExpr::CreateAdd(Expr, 139 MCConstantExpr::Create(MO.getOffset(), Ctx), 140 Ctx); 141 return MCOperand::CreateExpr(Expr); 142} 143 144 145void ARMMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 146 OutMI.setOpcode(MI->getOpcode()); 147 148 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 149 const MachineOperand &MO = MI->getOperand(i); 150 151 MCOperand MCOp; 152 switch (MO.getType()) { 153 default: 154 MI->dump(); 155 assert(0 && "unknown operand type"); 156 case MachineOperand::MO_Register: 157 // Ignore all non-CPSR implicit register operands. 158 if (MO.isImplicit() && MO.getReg() != ARM::CPSR) continue; 159 assert(!MO.getSubReg() && "Subregs should be eliminated!"); 160 MCOp = MCOperand::CreateReg(MO.getReg()); 161 break; 162 case MachineOperand::MO_Immediate: 163 MCOp = MCOperand::CreateImm(MO.getImm()); 164 break; 165 case MachineOperand::MO_MachineBasicBlock: 166 MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create( 167 MO.getMBB()->getSymbol(), Ctx)); 168 break; 169 case MachineOperand::MO_GlobalAddress: 170 MCOp = LowerSymbolRefOperand(MO, GetSymbolRef(MO)); 171 break; 172 case MachineOperand::MO_ExternalSymbol: 173 MCOp = LowerSymbolRefOperand(MO, GetExternalSymbolSymbol(MO)); 174 break; 175 case MachineOperand::MO_JumpTableIndex: 176 MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO)); 177 break; 178 case MachineOperand::MO_ConstantPoolIndex: 179 MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO)); 180 break; 181 case MachineOperand::MO_BlockAddress: 182 MCOp = LowerSymbolOperand(MO, Printer.GetBlockAddressSymbol( 183 MO.getBlockAddress())); 184 break; 185 case MachineOperand::MO_FPImmediate: 186 APFloat Val = MO.getFPImm()->getValueAPF(); 187 bool ignored; 188 Val.convert(APFloat::IEEEdouble, APFloat::rmTowardZero, &ignored); 189 MCOp = MCOperand::CreateFPImm(Val.convertToDouble()); 190 break; 191 } 192 193 OutMI.addOperand(MCOp); 194 } 195 196} 197