ARMMCInstLower.cpp revision b6ec8cae3cf437ea4e3d39ad209a0687df4686c3
19cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner//===-- ARMMCInstLower.cpp - Convert ARM MachineInstr to an MCInst --------===//
29cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner//
39cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner//                     The LLVM Compiler Infrastructure
49cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner//
59cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner// This file is distributed under the University of Illinois Open Source
69cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner// License. See LICENSE.TXT for details.
79cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner//
89cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner//===----------------------------------------------------------------------===//
99cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner//
109cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner// This file contains code to lower ARM MachineInstrs to their corresponding
119cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner// MCInst records.
129cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner//
139cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner//===----------------------------------------------------------------------===//
149cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner
151685caffedd0d0b351e0ec475d2529d90efec2fdJim Grosbach#include "ARM.h"
169cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner#include "ARMMCInstLower.h"
1796bc2173bb4909be0058e4eb2171f37a66e361ddChris Lattner#include "llvm/CodeGen/AsmPrinter.h"
1826edbcb8d5da5fb65816a97f740c9868fa798df4Jim Grosbach#include "llvm/Constants.h"
1996bc2173bb4909be0058e4eb2171f37a66e361ddChris Lattner#include "llvm/CodeGen/MachineBasicBlock.h"
206f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner#include "llvm/MC/MCAsmInfo.h"
216f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner#include "llvm/MC/MCContext.h"
226f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner#include "llvm/MC/MCExpr.h"
239cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner#include "llvm/MC/MCInst.h"
24d62f1b4168d4327c119642d28c26c836ae6717abChris Lattner#include "llvm/Target/Mangler.h"
256f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner#include "llvm/Support/raw_ostream.h"
266f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner#include "llvm/ADT/SmallString.h"
279cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattnerusing namespace llvm;
289cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner
29c686e33d12f84e1e1f5c96eadef851d078bab043Jim GrosbachMCSymbol *ARMMCInstLower::GetGlobalAddressSymbol(const GlobalValue *GV) const {
30c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach  return Printer.Mang->getSymbol(GV);
31c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach}
32c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach
33c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbachconst MCSymbolRefExpr *ARMMCInstLower::
34c686e33d12f84e1e1f5c96eadef851d078bab043Jim GrosbachGetSymbolRef(const MachineOperand &MO) const {
35c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach  assert(MO.isGlobal() && "Isn't a global address reference?");
366f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  // FIXME: HANDLE PLT references how??
37c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach
38c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach  const MCSymbolRefExpr *SymRef;
39c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach  const MCSymbol *Symbol = GetGlobalAddressSymbol(MO.getGlobal());
40c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach
416f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  switch (MO.getTargetFlags()) {
426f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  default: assert(0 && "Unknown target flag on GV operand");
43c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach  case 0:
44c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach    SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None, Ctx);
45c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach    break;
46c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach  case ARMII::MO_LO16:
47c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach    SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_LO16, Ctx);
48c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach    break;
49c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach  case ARMII::MO_HI16:
50c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach    SymRef = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_HI16, Ctx);
51c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach    break;
526f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  }
53fc16a8950c671b9434e60702ba31224c39ee133fJim Grosbach
54c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach  return SymRef;
556f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner}
566f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner
57292df8eb1f2e8967499161804e85772f5fd3a711Chris LattnerMCSymbol *ARMMCInstLower::
58292df8eb1f2e8967499161804e85772f5fd3a711Chris LattnerGetExternalSymbolSymbol(const MachineOperand &MO) const {
59292df8eb1f2e8967499161804e85772f5fd3a711Chris Lattner  // FIXME: HANDLE PLT references how??
60c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach  // FIXME: This probably needs to be merged with the above SymbolRef stuff
61c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach  // to handle :lower16: and :upper16: (?)
62292df8eb1f2e8967499161804e85772f5fd3a711Chris Lattner  switch (MO.getTargetFlags()) {
63292df8eb1f2e8967499161804e85772f5fd3a711Chris Lattner  default: assert(0 && "Unknown target flag on GV operand");
64292df8eb1f2e8967499161804e85772f5fd3a711Chris Lattner  case 0: break;
65292df8eb1f2e8967499161804e85772f5fd3a711Chris Lattner  }
66fc16a8950c671b9434e60702ba31224c39ee133fJim Grosbach
679ab19f25aaca858928901f9c520c666a4c815ebdChris Lattner  return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
68292df8eb1f2e8967499161804e85772f5fd3a711Chris Lattner}
69292df8eb1f2e8967499161804e85772f5fd3a711Chris Lattner
70292df8eb1f2e8967499161804e85772f5fd3a711Chris Lattner
716f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner
726f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris LattnerMCSymbol *ARMMCInstLower::
736f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris LattnerGetJumpTableSymbol(const MachineOperand &MO) const {
746f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  SmallString<256> Name;
7596bc2173bb4909be0058e4eb2171f37a66e361ddChris Lattner  raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "JTI"
7696bc2173bb4909be0058e4eb2171f37a66e361ddChris Lattner    << Printer.getFunctionNumber() << '_' << MO.getIndex();
77fc16a8950c671b9434e60702ba31224c39ee133fJim Grosbach
786f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  switch (MO.getTargetFlags()) {
79b6ec8cae3cf437ea4e3d39ad209a0687df4686c3Jim Grosbach  default: assert(0 && "Unknown target flag on jump table operand");
80b6ec8cae3cf437ea4e3d39ad209a0687df4686c3Jim Grosbach  case 0: break;
816f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  }
82fc16a8950c671b9434e60702ba31224c39ee133fJim Grosbach
836f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  // Create a symbol for the name.
849b97a73dedf736e14b04a3d1a153f10d25b2507bChris Lattner  return Ctx.GetOrCreateSymbol(Name.str());
856f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner}
866f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner
876f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris LattnerMCSymbol *ARMMCInstLower::
886f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris LattnerGetConstantPoolIndexSymbol(const MachineOperand &MO) const {
896f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  SmallString<256> Name;
9096bc2173bb4909be0058e4eb2171f37a66e361ddChris Lattner  raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "CPI"
9196bc2173bb4909be0058e4eb2171f37a66e361ddChris Lattner    << Printer.getFunctionNumber() << '_' << MO.getIndex();
92fc16a8950c671b9434e60702ba31224c39ee133fJim Grosbach
936f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  switch (MO.getTargetFlags()) {
94b6ec8cae3cf437ea4e3d39ad209a0687df4686c3Jim Grosbach  default: assert(0 && "Unknown target flag on CPI operand");
95b6ec8cae3cf437ea4e3d39ad209a0687df4686c3Jim Grosbach  case 0: break;
966f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  }
97fc16a8950c671b9434e60702ba31224c39ee133fJim Grosbach
986f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  // Create a symbol for the name.
999b97a73dedf736e14b04a3d1a153f10d25b2507bChris Lattner  return Ctx.GetOrCreateSymbol(Name.str());
1006f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner}
101fc16a8950c671b9434e60702ba31224c39ee133fJim Grosbach
1026f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris LattnerMCOperand ARMMCInstLower::
1036f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris LattnerLowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const {
1046f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  // FIXME: We would like an efficient form for this, so we don't have to do a
1056f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  // lot of extra uniquing.
1066f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx);
107fc16a8950c671b9434e60702ba31224c39ee133fJim Grosbach
1086f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  switch (MO.getTargetFlags()) {
109b6ec8cae3cf437ea4e3d39ad209a0687df4686c3Jim Grosbach  default: assert(0 && "Unknown target flag on Symbol operand");
110b6ec8cae3cf437ea4e3d39ad209a0687df4686c3Jim Grosbach  case 0: break;
1116f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  }
112fc16a8950c671b9434e60702ba31224c39ee133fJim Grosbach
1136f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  if (!MO.isJTI() && MO.getOffset())
1146f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner    Expr = MCBinaryExpr::CreateAdd(Expr,
1156f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner                                   MCConstantExpr::Create(MO.getOffset(), Ctx),
1166f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner                                   Ctx);
1176f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner  return MCOperand::CreateExpr(Expr);
1186f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner}
1196f99776f6c1d6cc93a62192099a0fd8cc2cc3a0cChris Lattner
120c686e33d12f84e1e1f5c96eadef851d078bab043Jim GrosbachMCOperand ARMMCInstLower::
121c686e33d12f84e1e1f5c96eadef851d078bab043Jim GrosbachLowerSymbolRefOperand(const MachineOperand &MO,
122c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach                      const MCSymbolRefExpr *Sym) const {
123c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach  const MCExpr *Expr = Sym;
124c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach  if (!MO.isJTI() && MO.getOffset())
125c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach    Expr = MCBinaryExpr::CreateAdd(Expr,
126c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach                                   MCConstantExpr::Create(MO.getOffset(), Ctx),
127c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach                                   Ctx);
128c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach  return MCOperand::CreateExpr(Expr);
129c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach}
130c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach
1319cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner
1329cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattnervoid ARMMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
1339cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner  OutMI.setOpcode(MI->getOpcode());
134fc16a8950c671b9434e60702ba31224c39ee133fJim Grosbach
1359cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
1369cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner    const MachineOperand &MO = MI->getOperand(i);
137fc16a8950c671b9434e60702ba31224c39ee133fJim Grosbach
1389cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner    MCOperand MCOp;
1399cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner    switch (MO.getType()) {
1409cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner    default:
1419cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner      MI->dump();
1429cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner      assert(0 && "unknown operand type");
1439cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner    case MachineOperand::MO_Register:
1441685caffedd0d0b351e0ec475d2529d90efec2fdJim Grosbach      // Ignore all non-CPSR implicit register operands.
1451685caffedd0d0b351e0ec475d2529d90efec2fdJim Grosbach      if (MO.isImplicit() && MO.getReg() != ARM::CPSR) continue;
146e8ea011cc766b37a957d5966655526096bf49feaAnton Korobeynikov      assert(!MO.getSubReg() && "Subregs should be eliminated!");
1479cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner      MCOp = MCOperand::CreateReg(MO.getReg());
1489cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner      break;
1499cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner    case MachineOperand::MO_Immediate:
1509cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner      MCOp = MCOperand::CreateImm(MO.getImm());
1519cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner      break;
1529cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner    case MachineOperand::MO_MachineBasicBlock:
1539cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner      MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
1541b2eb0e8a6aaf034675b17be6d853cb1c666200fChris Lattner                       MO.getMBB()->getSymbol(), Ctx));
1559cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner      break;
1569cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner    case MachineOperand::MO_GlobalAddress:
157c686e33d12f84e1e1f5c96eadef851d078bab043Jim Grosbach      MCOp = LowerSymbolRefOperand(MO, GetSymbolRef(MO));
1589cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner      break;
1599cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner    case MachineOperand::MO_ExternalSymbol:
1609cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner      MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
1619cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner      break;
1629cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner    case MachineOperand::MO_JumpTableIndex:
1639cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner      MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO));
1649cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner      break;
1659cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner    case MachineOperand::MO_ConstantPoolIndex:
1669cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner      MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO));
1679cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner      break;
168ddb16df91257e4c4d2be5343e2c7c7ecbfbe8bf4Bob Wilson    case MachineOperand::MO_BlockAddress:
169ddb16df91257e4c4d2be5343e2c7c7ecbfbe8bf4Bob Wilson      MCOp = LowerSymbolOperand(MO, Printer.GetBlockAddressSymbol(
170ddb16df91257e4c4d2be5343e2c7c7ecbfbe8bf4Bob Wilson                                              MO.getBlockAddress()));
171ddb16df91257e4c4d2be5343e2c7c7ecbfbe8bf4Bob Wilson      break;
17226edbcb8d5da5fb65816a97f740c9868fa798df4Jim Grosbach    case MachineOperand::MO_FPImmediate:
1731d51c41a457b99d646e3a9b9fae1e913f7a60dc0Jim Grosbach      APFloat Val = MO.getFPImm()->getValueAPF();
1741d51c41a457b99d646e3a9b9fae1e913f7a60dc0Jim Grosbach      bool ignored;
1751d51c41a457b99d646e3a9b9fae1e913f7a60dc0Jim Grosbach      Val.convert(APFloat::IEEEdouble, APFloat::rmTowardZero, &ignored);
1761d51c41a457b99d646e3a9b9fae1e913f7a60dc0Jim Grosbach      MCOp = MCOperand::CreateFPImm(Val.convertToDouble());
17726edbcb8d5da5fb65816a97f740c9868fa798df4Jim Grosbach      break;
1789cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner    }
179fc16a8950c671b9434e60702ba31224c39ee133fJim Grosbach
1809cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner    OutMI.addOperand(MCOp);
1819cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner  }
182fc16a8950c671b9434e60702ba31224c39ee133fJim Grosbach
1839cf0eb5e58fa42802af7e5776b39909516ca74e7Chris Lattner}
184