1 //==-- AArch64MCInstLower.cpp - Convert AArch64 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 AArch64 MachineInstrs to their corresponding
13 //===----------------------------------------------------------------------===//
15 #include "AArch64MCInstLower.h"
16 #include "MCTargetDesc/AArch64MCExpr.h"
17 #include "Utils/AArch64BaseInfo.h"
18 #include "llvm/CodeGen/AsmPrinter.h"
19 #include "llvm/CodeGen/MachineBasicBlock.h"
20 #include "llvm/CodeGen/MachineInstr.h"
21 #include "llvm/IR/Mangler.h"
22 #include "llvm/MC/MCExpr.h"
23 #include "llvm/MC/MCInst.h"
24 #include "llvm/Support/CodeGen.h"
25 #include "llvm/Target/TargetMachine.h"
28 AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
29 : Ctx(ctx), Printer(printer), TargetTriple(printer.getTargetTriple()) {}
32 AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
33 return Printer.getSymbol(MO.getGlobal());
37 AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
38 return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
41 MCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO,
42 MCSymbol *Sym) const {
43 // FIXME: We would like an efficient form for this, so we don't have to do a
44 // lot of extra uniquing.
45 MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
46 if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
47 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
48 RefKind = MCSymbolRefExpr::VK_GOTPAGE;
49 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
50 AArch64II::MO_PAGEOFF)
51 RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF;
53 llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
54 } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
55 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
56 RefKind = MCSymbolRefExpr::VK_TLVPPAGE;
57 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
58 AArch64II::MO_PAGEOFF)
59 RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF;
61 llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
63 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
64 RefKind = MCSymbolRefExpr::VK_PAGE;
65 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
66 AArch64II::MO_PAGEOFF)
67 RefKind = MCSymbolRefExpr::VK_PAGEOFF;
69 const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, RefKind, Ctx);
70 if (!MO.isJTI() && MO.getOffset())
71 Expr = MCBinaryExpr::CreateAdd(
72 Expr, MCConstantExpr::Create(MO.getOffset(), Ctx), Ctx);
73 return MCOperand::CreateExpr(Expr);
76 MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
77 MCSymbol *Sym) const {
78 uint32_t RefFlags = 0;
80 if (MO.getTargetFlags() & AArch64II::MO_GOT)
81 RefFlags |= AArch64MCExpr::VK_GOT;
82 else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
83 TLSModel::Model Model;
85 const GlobalValue *GV = MO.getGlobal();
86 Model = Printer.TM.getTLSModel(GV);
88 assert(MO.isSymbol() &&
89 StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" &&
90 "unexpected external TLS symbol");
91 Model = TLSModel::GeneralDynamic;
94 case TLSModel::InitialExec:
95 RefFlags |= AArch64MCExpr::VK_GOTTPREL;
97 case TLSModel::LocalExec:
98 RefFlags |= AArch64MCExpr::VK_TPREL;
100 case TLSModel::LocalDynamic:
101 RefFlags |= AArch64MCExpr::VK_DTPREL;
103 case TLSModel::GeneralDynamic:
104 RefFlags |= AArch64MCExpr::VK_TLSDESC;
108 // No modifier means this is a generic reference, classified as absolute for
109 // the cases where it matters (:abs_g0: etc).
110 RefFlags |= AArch64MCExpr::VK_ABS;
113 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
114 RefFlags |= AArch64MCExpr::VK_PAGE;
115 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
116 AArch64II::MO_PAGEOFF)
117 RefFlags |= AArch64MCExpr::VK_PAGEOFF;
118 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
119 RefFlags |= AArch64MCExpr::VK_G3;
120 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
121 RefFlags |= AArch64MCExpr::VK_G2;
122 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
123 RefFlags |= AArch64MCExpr::VK_G1;
124 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
125 RefFlags |= AArch64MCExpr::VK_G0;
127 if (MO.getTargetFlags() & AArch64II::MO_NC)
128 RefFlags |= AArch64MCExpr::VK_NC;
131 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, Ctx);
132 if (!MO.isJTI() && MO.getOffset())
133 Expr = MCBinaryExpr::CreateAdd(
134 Expr, MCConstantExpr::Create(MO.getOffset(), Ctx), Ctx);
136 AArch64MCExpr::VariantKind RefKind;
137 RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
138 Expr = AArch64MCExpr::Create(Expr, RefKind, Ctx);
140 return MCOperand::CreateExpr(Expr);
143 MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
144 MCSymbol *Sym) const {
145 if (TargetTriple.isOSDarwin())
146 return lowerSymbolOperandDarwin(MO, Sym);
148 assert(TargetTriple.isOSBinFormatELF() && "Expect Darwin or ELF target");
149 return lowerSymbolOperandELF(MO, Sym);
152 bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
153 MCOperand &MCOp) const {
154 switch (MO.getType()) {
156 llvm_unreachable("unknown operand type");
157 case MachineOperand::MO_Register:
158 // Ignore all implicit register operands.
161 MCOp = MCOperand::CreateReg(MO.getReg());
163 case MachineOperand::MO_RegisterMask:
164 // Regmasks are like implicit defs.
166 case MachineOperand::MO_Immediate:
167 MCOp = MCOperand::CreateImm(MO.getImm());
169 case MachineOperand::MO_MachineBasicBlock:
170 MCOp = MCOperand::CreateExpr(
171 MCSymbolRefExpr::Create(MO.getMBB()->getSymbol(), Ctx));
173 case MachineOperand::MO_GlobalAddress:
174 MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
176 case MachineOperand::MO_ExternalSymbol:
177 MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
179 case MachineOperand::MO_JumpTableIndex:
180 MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
182 case MachineOperand::MO_ConstantPoolIndex:
183 MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
185 case MachineOperand::MO_BlockAddress:
186 MCOp = LowerSymbolOperand(
187 MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
193 void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
194 OutMI.setOpcode(MI->getOpcode());
196 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
198 if (lowerOperand(MI->getOperand(i), MCOp))
199 OutMI.addOperand(MCOp);