1212793Sdim//===-- ARMMCInstLower.cpp - Convert ARM MachineInstr to an MCInst --------===//
2212793Sdim//
3212793Sdim//                     The LLVM Compiler Infrastructure
4212793Sdim//
5212793Sdim// This file is distributed under the University of Illinois Open Source
6212793Sdim// License. See LICENSE.TXT for details.
7212793Sdim//
8212793Sdim//===----------------------------------------------------------------------===//
9212793Sdim//
10212793Sdim// This file contains code to lower ARM MachineInstrs to their corresponding
11212793Sdim// MCInst records.
12212793Sdim//
13212793Sdim//===----------------------------------------------------------------------===//
14212793Sdim
15218893Sdim#include "ARM.h"
16218893Sdim#include "ARMAsmPrinter.h"
17226633Sdim#include "MCTargetDesc/ARMMCExpr.h"
18212793Sdim#include "llvm/CodeGen/MachineBasicBlock.h"
19249423Sdim#include "llvm/IR/Constants.h"
20212793Sdim#include "llvm/MC/MCExpr.h"
21212793Sdim#include "llvm/MC/MCInst.h"
22212793Sdim#include "llvm/Target/Mangler.h"
23212793Sdimusing namespace llvm;
24212793Sdim
25212793Sdim
26224145SdimMCOperand ARMAsmPrinter::GetSymbolRef(const MachineOperand &MO,
27224145Sdim                                      const MCSymbol *Symbol) {
28218893Sdim  const MCExpr *Expr;
29212793Sdim  switch (MO.getTargetFlags()) {
30218893Sdim  default: {
31224145Sdim    Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
32224145Sdim                                   OutContext);
33218893Sdim    switch (MO.getTargetFlags()) {
34234353Sdim    default: llvm_unreachable("Unknown target flag on symbol operand");
35218893Sdim    case 0:
36218893Sdim      break;
37218893Sdim    case ARMII::MO_LO16:
38224145Sdim      Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
39224145Sdim                                     OutContext);
40224145Sdim      Expr = ARMMCExpr::CreateLower16(Expr, OutContext);
41218893Sdim      break;
42218893Sdim    case ARMII::MO_HI16:
43224145Sdim      Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_None,
44224145Sdim                                     OutContext);
45224145Sdim      Expr = ARMMCExpr::CreateUpper16(Expr, OutContext);
46218893Sdim      break;
47218893Sdim    }
48218893Sdim    break;
49212793Sdim  }
50212793Sdim
51218893Sdim  case ARMII::MO_PLT:
52224145Sdim    Expr = MCSymbolRefExpr::Create(Symbol, MCSymbolRefExpr::VK_ARM_PLT,
53224145Sdim                                   OutContext);
54218893Sdim    break;
55212793Sdim  }
56212793Sdim
57212793Sdim  if (!MO.isJTI() && MO.getOffset())
58212793Sdim    Expr = MCBinaryExpr::CreateAdd(Expr,
59224145Sdim                                   MCConstantExpr::Create(MO.getOffset(),
60224145Sdim                                                          OutContext),
61224145Sdim                                   OutContext);
62212793Sdim  return MCOperand::CreateExpr(Expr);
63218893Sdim
64212793Sdim}
65212793Sdim
66224145Sdimbool ARMAsmPrinter::lowerOperand(const MachineOperand &MO,
67224145Sdim                                 MCOperand &MCOp) {
68224145Sdim  switch (MO.getType()) {
69234353Sdim  default: llvm_unreachable("unknown operand type");
70224145Sdim  case MachineOperand::MO_Register:
71224145Sdim    // Ignore all non-CPSR implicit register operands.
72224145Sdim    if (MO.isImplicit() && MO.getReg() != ARM::CPSR)
73224145Sdim      return false;
74224145Sdim    assert(!MO.getSubReg() && "Subregs should be eliminated!");
75224145Sdim    MCOp = MCOperand::CreateReg(MO.getReg());
76224145Sdim    break;
77224145Sdim  case MachineOperand::MO_Immediate:
78224145Sdim    MCOp = MCOperand::CreateImm(MO.getImm());
79224145Sdim    break;
80224145Sdim  case MachineOperand::MO_MachineBasicBlock:
81224145Sdim    MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
82224145Sdim        MO.getMBB()->getSymbol(), OutContext));
83224145Sdim    break;
84224145Sdim  case MachineOperand::MO_GlobalAddress:
85263508Sdim    MCOp = GetSymbolRef(MO, getSymbol(MO.getGlobal()));
86224145Sdim    break;
87224145Sdim  case MachineOperand::MO_ExternalSymbol:
88224145Sdim   MCOp = GetSymbolRef(MO,
89224145Sdim                        GetExternalSymbolSymbol(MO.getSymbolName()));
90224145Sdim    break;
91224145Sdim  case MachineOperand::MO_JumpTableIndex:
92224145Sdim    MCOp = GetSymbolRef(MO, GetJTISymbol(MO.getIndex()));
93224145Sdim    break;
94224145Sdim  case MachineOperand::MO_ConstantPoolIndex:
95224145Sdim    MCOp = GetSymbolRef(MO, GetCPISymbol(MO.getIndex()));
96224145Sdim    break;
97224145Sdim  case MachineOperand::MO_BlockAddress:
98224145Sdim    MCOp = GetSymbolRef(MO, GetBlockAddressSymbol(MO.getBlockAddress()));
99224145Sdim    break;
100224145Sdim  case MachineOperand::MO_FPImmediate: {
101224145Sdim    APFloat Val = MO.getFPImm()->getValueAPF();
102224145Sdim    bool ignored;
103224145Sdim    Val.convert(APFloat::IEEEdouble, APFloat::rmTowardZero, &ignored);
104224145Sdim    MCOp = MCOperand::CreateFPImm(Val.convertToDouble());
105224145Sdim    break;
106224145Sdim  }
107234353Sdim  case MachineOperand::MO_RegisterMask:
108234353Sdim    // Ignore call clobbers.
109234353Sdim    return false;
110224145Sdim  }
111224145Sdim  return true;
112224145Sdim}
113224145Sdim
114218893Sdimvoid llvm::LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
115218893Sdim                                        ARMAsmPrinter &AP) {
116218893Sdim  OutMI.setOpcode(MI->getOpcode());
117212793Sdim
118212793Sdim  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
119212793Sdim    const MachineOperand &MO = MI->getOperand(i);
120218893Sdim
121212793Sdim    MCOperand MCOp;
122224145Sdim    if (AP.lowerOperand(MO, MCOp))
123224145Sdim      OutMI.addOperand(MCOp);
124212793Sdim  }
125212793Sdim}
126