1 //===-- ARMMCInstLower.cpp - Convert ARM MachineInstr to an MCInst --------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains code to lower ARM MachineInstrs to their corresponding
13 //===----------------------------------------------------------------------===//
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"
29 MCSymbol
*ARMMCInstLower::GetGlobalAddressSymbol(const GlobalValue
*GV
) const {
30 return Printer
.Mang
->getSymbol(GV
);
33 const MCSymbolRefExpr
*ARMMCInstLower::
34 GetSymbolRef(const MachineOperand
&MO
) const {
35 assert(MO
.isGlobal() && "Isn't a global address reference?");
37 const MCSymbolRefExpr
*SymRef
;
38 const MCSymbol
*Symbol
= GetGlobalAddressSymbol(MO
.getGlobal());
40 switch (MO
.getTargetFlags()) {
41 default: assert(0 && "Unknown target flag on GV operand");
43 SymRef
= MCSymbolRefExpr::Create(Symbol
, MCSymbolRefExpr::VK_None
, Ctx
);
46 SymRef
= MCSymbolRefExpr::Create(Symbol
, MCSymbolRefExpr::VK_ARM_LO16
, Ctx
);
49 SymRef
= MCSymbolRefExpr::Create(Symbol
, MCSymbolRefExpr::VK_ARM_HI16
, Ctx
);
52 SymRef
= MCSymbolRefExpr::Create(Symbol
, MCSymbolRefExpr::VK_ARM_PLT
, Ctx
);
59 const MCSymbolRefExpr
*ARMMCInstLower::
60 GetExternalSymbolSymbol(const MachineOperand
&MO
) const {
61 const MCSymbolRefExpr
*SymRef
;
62 const MCSymbol
*Symbol
= Printer
.GetExternalSymbolSymbol(MO
.getSymbolName());
64 switch (MO
.getTargetFlags()) {
65 default: assert(0 && "Unknown target flag on external symbol operand");
67 SymRef
= MCSymbolRefExpr::Create(Symbol
, MCSymbolRefExpr::VK_None
, Ctx
);
70 SymRef
= MCSymbolRefExpr::Create(Symbol
, MCSymbolRefExpr::VK_ARM_LO16
, Ctx
);
73 SymRef
= MCSymbolRefExpr::Create(Symbol
, MCSymbolRefExpr::VK_ARM_HI16
, Ctx
);
76 SymRef
= MCSymbolRefExpr::Create(Symbol
, MCSymbolRefExpr::VK_ARM_PLT
, Ctx
);
85 MCSymbol
*ARMMCInstLower::
86 GetJumpTableSymbol(const MachineOperand
&MO
) const {
87 SmallString
<256> Name
;
88 raw_svector_ostream(Name
) << Printer
.MAI
->getPrivateGlobalPrefix() << "JTI"
89 << Printer
.getFunctionNumber() << '_' << MO
.getIndex();
91 switch (MO
.getTargetFlags()) {
92 default: assert(0 && "Unknown target flag on jump table operand");
96 // Create a symbol for the name.
97 return Ctx
.GetOrCreateSymbol(Name
.str());
100 MCSymbol
*ARMMCInstLower::
101 GetConstantPoolIndexSymbol(const MachineOperand
&MO
) const {
102 SmallString
<256> Name
;
103 raw_svector_ostream(Name
) << Printer
.MAI
->getPrivateGlobalPrefix() << "CPI"
104 << Printer
.getFunctionNumber() << '_' << MO
.getIndex();
106 switch (MO
.getTargetFlags()) {
107 default: assert(0 && "Unknown target flag on CPI operand");
111 // Create a symbol for the name.
112 return Ctx
.GetOrCreateSymbol(Name
.str());
115 MCOperand
ARMMCInstLower::
116 LowerSymbolOperand(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
);
121 switch (MO
.getTargetFlags()) {
122 default: assert(0 && "Unknown target flag on Symbol operand");
126 if (!MO
.isJTI() && MO
.getOffset())
127 Expr
= MCBinaryExpr::CreateAdd(Expr
,
128 MCConstantExpr::Create(MO
.getOffset(), Ctx
),
130 return MCOperand::CreateExpr(Expr
);
133 MCOperand
ARMMCInstLower::
134 LowerSymbolRefOperand(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
),
141 return MCOperand::CreateExpr(Expr
);
145 void ARMMCInstLower::Lower(const MachineInstr
*MI
, MCInst
&OutMI
) const {
146 OutMI
.setOpcode(MI
->getOpcode());
148 for (unsigned i
= 0, e
= MI
->getNumOperands(); i
!= e
; ++i
) {
149 const MachineOperand
&MO
= MI
->getOperand(i
);
152 switch (MO
.getType()) {
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());
162 case MachineOperand::MO_Immediate
:
163 MCOp
= MCOperand::CreateImm(MO
.getImm());
165 case MachineOperand::MO_MachineBasicBlock
:
166 MCOp
= MCOperand::CreateExpr(MCSymbolRefExpr::Create(
167 MO
.getMBB()->getSymbol(), Ctx
));
169 case MachineOperand::MO_GlobalAddress
:
170 MCOp
= LowerSymbolRefOperand(MO
, GetSymbolRef(MO
));
172 case MachineOperand::MO_ExternalSymbol
:
173 MCOp
= LowerSymbolRefOperand(MO
, GetExternalSymbolSymbol(MO
));
175 case MachineOperand::MO_JumpTableIndex
:
176 MCOp
= LowerSymbolOperand(MO
, GetJumpTableSymbol(MO
));
178 case MachineOperand::MO_ConstantPoolIndex
:
179 MCOp
= LowerSymbolOperand(MO
, GetConstantPoolIndexSymbol(MO
));
181 case MachineOperand::MO_BlockAddress
:
182 MCOp
= LowerSymbolOperand(MO
, Printer
.GetBlockAddressSymbol(
183 MO
.getBlockAddress()));
185 case MachineOperand::MO_FPImmediate
:
186 APFloat Val
= MO
.getFPImm()->getValueAPF();
188 Val
.convert(APFloat::IEEEdouble
, APFloat::rmTowardZero
, &ignored
);
189 MCOp
= MCOperand::CreateFPImm(Val
.convertToDouble());
193 OutMI
.addOperand(MCOp
);