AArch64MCInstLower.cpp revision 280031
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, AsmPrinter &printer) 29 : Ctx(ctx), Printer(printer), TargetTriple(printer.getTargetTriple()) {} 30 31MCSymbol * 32AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const { 33 return Printer.getSymbol(MO.getGlobal()); 34} 35 36MCSymbol * 37AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const { 38 return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); 39} 40 41MCOperand 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; 52 else 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; 60 else 61 llvm_unreachable("Unexpected target flags with MO_TLS on GV operand"); 62 } else { 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; 68 } 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); 74} 75 76MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO, 77 MCSymbol *Sym) const { 78 uint32_t RefFlags = 0; 79 80 if (MO.getTargetFlags() & AArch64II::MO_GOT) 81 RefFlags |= AArch64MCExpr::VK_GOT; 82 else if (MO.getTargetFlags() & AArch64II::MO_TLS) { 83 TLSModel::Model Model; 84 if (MO.isGlobal()) { 85 const GlobalValue *GV = MO.getGlobal(); 86 Model = Printer.TM.getTLSModel(GV); 87 } else { 88 assert(MO.isSymbol() && 89 StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" && 90 "unexpected external TLS symbol"); 91 Model = TLSModel::GeneralDynamic; 92 } 93 switch (Model) { 94 case TLSModel::InitialExec: 95 RefFlags |= AArch64MCExpr::VK_GOTTPREL; 96 break; 97 case TLSModel::LocalExec: 98 RefFlags |= AArch64MCExpr::VK_TPREL; 99 break; 100 case TLSModel::LocalDynamic: 101 RefFlags |= AArch64MCExpr::VK_DTPREL; 102 break; 103 case TLSModel::GeneralDynamic: 104 RefFlags |= AArch64MCExpr::VK_TLSDESC; 105 break; 106 } 107 } else { 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; 111 } 112 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; 126 127 if (MO.getTargetFlags() & AArch64II::MO_NC) 128 RefFlags |= AArch64MCExpr::VK_NC; 129 130 const MCExpr *Expr = 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); 135 136 AArch64MCExpr::VariantKind RefKind; 137 RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags); 138 Expr = AArch64MCExpr::Create(Expr, RefKind, Ctx); 139 140 return MCOperand::CreateExpr(Expr); 141} 142 143MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO, 144 MCSymbol *Sym) const { 145 if (TargetTriple.isOSDarwin()) 146 return lowerSymbolOperandDarwin(MO, Sym); 147 148 assert(TargetTriple.isOSBinFormatELF() && "Expect Darwin or ELF target"); 149 return lowerSymbolOperandELF(MO, Sym); 150} 151 152bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO, 153 MCOperand &MCOp) const { 154 switch (MO.getType()) { 155 default: 156 llvm_unreachable("unknown operand type"); 157 case MachineOperand::MO_Register: 158 // Ignore all implicit register operands. 159 if (MO.isImplicit()) 160 return false; 161 MCOp = MCOperand::CreateReg(MO.getReg()); 162 break; 163 case MachineOperand::MO_RegisterMask: 164 // Regmasks are like implicit defs. 165 return false; 166 case MachineOperand::MO_Immediate: 167 MCOp = MCOperand::CreateImm(MO.getImm()); 168 break; 169 case MachineOperand::MO_MachineBasicBlock: 170 MCOp = MCOperand::CreateExpr( 171 MCSymbolRefExpr::Create(MO.getMBB()->getSymbol(), Ctx)); 172 break; 173 case MachineOperand::MO_GlobalAddress: 174 MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); 175 break; 176 case MachineOperand::MO_ExternalSymbol: 177 MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); 178 break; 179 case MachineOperand::MO_JumpTableIndex: 180 MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex())); 181 break; 182 case MachineOperand::MO_ConstantPoolIndex: 183 MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex())); 184 break; 185 case MachineOperand::MO_BlockAddress: 186 MCOp = LowerSymbolOperand( 187 MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress())); 188 break; 189 } 190 return true; 191} 192 193void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 194 OutMI.setOpcode(MI->getOpcode()); 195 196 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 197 MCOperand MCOp; 198 if (lowerOperand(MI->getOperand(i), MCOp)) 199 OutMI.addOperand(MCOp); 200 } 201} 202