AArch64MCInstLower.cpp revision cd81d94322a39503e4a3e87b6ee03d4fcb3465fb
1//==-- AArch64MCInstLower.cpp - Convert AArch64 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 AArch64 MachineInstrs to their corresponding 11// MCInst records. 12// 13//===----------------------------------------------------------------------===// 14 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" 26using namespace llvm; 27 28AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, Mangler &mang, 29 AsmPrinter &printer) 30 : Ctx(ctx), Printer(printer), TargetTriple(printer.getTargetTriple()) {} 31 32MCSymbol * 33AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const { 34 return Printer.getSymbol(MO.getGlobal()); 35} 36 37MCSymbol * 38AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const { 39 return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); 40} 41 42MCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO, 43 MCSymbol *Sym) const { 44 // FIXME: We would like an efficient form for this, so we don't have to do a 45 // lot of extra uniquing. 46 MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 47 if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) { 48 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 49 RefKind = MCSymbolRefExpr::VK_GOTPAGE; 50 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 51 AArch64II::MO_PAGEOFF) 52 RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF; 53 else 54 llvm_unreachable("Unexpected target flags with MO_GOT on GV operand"); 55 } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) { 56 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 57 RefKind = MCSymbolRefExpr::VK_TLVPPAGE; 58 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 59 AArch64II::MO_PAGEOFF) 60 RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF; 61 else 62 llvm_unreachable("Unexpected target flags with MO_TLS on GV operand"); 63 } else { 64 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 65 RefKind = MCSymbolRefExpr::VK_PAGE; 66 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 67 AArch64II::MO_PAGEOFF) 68 RefKind = MCSymbolRefExpr::VK_PAGEOFF; 69 } 70 const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, RefKind, Ctx); 71 if (!MO.isJTI() && MO.getOffset()) 72 Expr = MCBinaryExpr::CreateAdd( 73 Expr, MCConstantExpr::Create(MO.getOffset(), Ctx), Ctx); 74 return MCOperand::CreateExpr(Expr); 75} 76 77MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO, 78 MCSymbol *Sym) const { 79 uint32_t RefFlags = 0; 80 81 if (MO.getTargetFlags() & AArch64II::MO_GOT) 82 RefFlags |= AArch64MCExpr::VK_GOT; 83 else if (MO.getTargetFlags() & AArch64II::MO_TLS) { 84 TLSModel::Model Model; 85 if (MO.isGlobal()) { 86 const GlobalValue *GV = MO.getGlobal(); 87 Model = Printer.TM.getTLSModel(GV); 88 } else { 89 assert(MO.isSymbol() && 90 StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" && 91 "unexpected external TLS symbol"); 92 Model = TLSModel::GeneralDynamic; 93 } 94 switch (Model) { 95 case TLSModel::InitialExec: 96 RefFlags |= AArch64MCExpr::VK_GOTTPREL; 97 break; 98 case TLSModel::LocalExec: 99 RefFlags |= AArch64MCExpr::VK_TPREL; 100 break; 101 case TLSModel::LocalDynamic: 102 RefFlags |= AArch64MCExpr::VK_DTPREL; 103 break; 104 case TLSModel::GeneralDynamic: 105 RefFlags |= AArch64MCExpr::VK_TLSDESC; 106 break; 107 } 108 } else { 109 // No modifier means this is a generic reference, classified as absolute for 110 // the cases where it matters (:abs_g0: etc). 111 RefFlags |= AArch64MCExpr::VK_ABS; 112 } 113 114 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 115 RefFlags |= AArch64MCExpr::VK_PAGE; 116 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 117 AArch64II::MO_PAGEOFF) 118 RefFlags |= AArch64MCExpr::VK_PAGEOFF; 119 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3) 120 RefFlags |= AArch64MCExpr::VK_G3; 121 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2) 122 RefFlags |= AArch64MCExpr::VK_G2; 123 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1) 124 RefFlags |= AArch64MCExpr::VK_G1; 125 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0) 126 RefFlags |= AArch64MCExpr::VK_G0; 127 128 if (MO.getTargetFlags() & AArch64II::MO_NC) 129 RefFlags |= AArch64MCExpr::VK_NC; 130 131 const MCExpr *Expr = 132 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, Ctx); 133 if (!MO.isJTI() && MO.getOffset()) 134 Expr = MCBinaryExpr::CreateAdd( 135 Expr, MCConstantExpr::Create(MO.getOffset(), Ctx), Ctx); 136 137 AArch64MCExpr::VariantKind RefKind; 138 RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags); 139 Expr = AArch64MCExpr::Create(Expr, RefKind, Ctx); 140 141 return MCOperand::CreateExpr(Expr); 142} 143 144MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO, 145 MCSymbol *Sym) const { 146 if (TargetTriple.isOSDarwin()) 147 return lowerSymbolOperandDarwin(MO, Sym); 148 149 assert(TargetTriple.isOSBinFormatELF() && "Expect Darwin or ELF target"); 150 return lowerSymbolOperandELF(MO, Sym); 151} 152 153bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO, 154 MCOperand &MCOp) const { 155 switch (MO.getType()) { 156 default: 157 llvm_unreachable("unknown operand type"); 158 case MachineOperand::MO_Register: 159 // Ignore all implicit register operands. 160 if (MO.isImplicit()) 161 return false; 162 MCOp = MCOperand::CreateReg(MO.getReg()); 163 break; 164 case MachineOperand::MO_RegisterMask: 165 // Regmasks are like implicit defs. 166 return false; 167 case MachineOperand::MO_Immediate: 168 MCOp = MCOperand::CreateImm(MO.getImm()); 169 break; 170 case MachineOperand::MO_MachineBasicBlock: 171 MCOp = MCOperand::CreateExpr( 172 MCSymbolRefExpr::Create(MO.getMBB()->getSymbol(), Ctx)); 173 break; 174 case MachineOperand::MO_GlobalAddress: 175 MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); 176 break; 177 case MachineOperand::MO_ExternalSymbol: 178 MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); 179 break; 180 case MachineOperand::MO_JumpTableIndex: 181 MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex())); 182 break; 183 case MachineOperand::MO_ConstantPoolIndex: 184 MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex())); 185 break; 186 case MachineOperand::MO_BlockAddress: 187 MCOp = LowerSymbolOperand( 188 MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress())); 189 break; 190 } 191 return true; 192} 193 194void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 195 OutMI.setOpcode(MI->getOpcode()); 196 197 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 198 MCOperand MCOp; 199 if (lowerOperand(MI->getOperand(i), MCOp)) 200 OutMI.addOperand(MCOp); 201 } 202} 203