LLVM API Documentation
00001 //==-- AArch64MCInstLower.cpp - Convert AArch64 MachineInstr to an MCInst --==// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file contains code to lower AArch64 MachineInstrs to their corresponding 00011 // MCInst records. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "AArch64MCInstLower.h" 00016 #include "MCTargetDesc/AArch64MCExpr.h" 00017 #include "Utils/AArch64BaseInfo.h" 00018 #include "llvm/CodeGen/AsmPrinter.h" 00019 #include "llvm/CodeGen/MachineBasicBlock.h" 00020 #include "llvm/CodeGen/MachineInstr.h" 00021 #include "llvm/IR/Mangler.h" 00022 #include "llvm/MC/MCExpr.h" 00023 #include "llvm/MC/MCInst.h" 00024 #include "llvm/Support/CodeGen.h" 00025 #include "llvm/Target/TargetMachine.h" 00026 using namespace llvm; 00027 00028 AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer) 00029 : Ctx(ctx), Printer(printer), TargetTriple(printer.getTargetTriple()) {} 00030 00031 MCSymbol * 00032 AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const { 00033 return Printer.getSymbol(MO.getGlobal()); 00034 } 00035 00036 MCSymbol * 00037 AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const { 00038 return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); 00039 } 00040 00041 MCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO, 00042 MCSymbol *Sym) const { 00043 // FIXME: We would like an efficient form for this, so we don't have to do a 00044 // lot of extra uniquing. 00045 MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 00046 if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) { 00047 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 00048 RefKind = MCSymbolRefExpr::VK_GOTPAGE; 00049 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 00050 AArch64II::MO_PAGEOFF) 00051 RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF; 00052 else 00053 llvm_unreachable("Unexpected target flags with MO_GOT on GV operand"); 00054 } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) { 00055 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 00056 RefKind = MCSymbolRefExpr::VK_TLVPPAGE; 00057 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 00058 AArch64II::MO_PAGEOFF) 00059 RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF; 00060 else 00061 llvm_unreachable("Unexpected target flags with MO_TLS on GV operand"); 00062 } else { 00063 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 00064 RefKind = MCSymbolRefExpr::VK_PAGE; 00065 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 00066 AArch64II::MO_PAGEOFF) 00067 RefKind = MCSymbolRefExpr::VK_PAGEOFF; 00068 } 00069 const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, RefKind, Ctx); 00070 if (!MO.isJTI() && MO.getOffset()) 00071 Expr = MCBinaryExpr::CreateAdd( 00072 Expr, MCConstantExpr::Create(MO.getOffset(), Ctx), Ctx); 00073 return MCOperand::CreateExpr(Expr); 00074 } 00075 00076 MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO, 00077 MCSymbol *Sym) const { 00078 uint32_t RefFlags = 0; 00079 00080 if (MO.getTargetFlags() & AArch64II::MO_GOT) 00081 RefFlags |= AArch64MCExpr::VK_GOT; 00082 else if (MO.getTargetFlags() & AArch64II::MO_TLS) { 00083 TLSModel::Model Model; 00084 if (MO.isGlobal()) { 00085 const GlobalValue *GV = MO.getGlobal(); 00086 Model = Printer.TM.getTLSModel(GV); 00087 } else { 00088 assert(MO.isSymbol() && 00089 StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" && 00090 "unexpected external TLS symbol"); 00091 Model = TLSModel::GeneralDynamic; 00092 } 00093 switch (Model) { 00094 case TLSModel::InitialExec: 00095 RefFlags |= AArch64MCExpr::VK_GOTTPREL; 00096 break; 00097 case TLSModel::LocalExec: 00098 RefFlags |= AArch64MCExpr::VK_TPREL; 00099 break; 00100 case TLSModel::LocalDynamic: 00101 RefFlags |= AArch64MCExpr::VK_DTPREL; 00102 break; 00103 case TLSModel::GeneralDynamic: 00104 RefFlags |= AArch64MCExpr::VK_TLSDESC; 00105 break; 00106 } 00107 } else { 00108 // No modifier means this is a generic reference, classified as absolute for 00109 // the cases where it matters (:abs_g0: etc). 00110 RefFlags |= AArch64MCExpr::VK_ABS; 00111 } 00112 00113 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 00114 RefFlags |= AArch64MCExpr::VK_PAGE; 00115 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 00116 AArch64II::MO_PAGEOFF) 00117 RefFlags |= AArch64MCExpr::VK_PAGEOFF; 00118 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3) 00119 RefFlags |= AArch64MCExpr::VK_G3; 00120 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2) 00121 RefFlags |= AArch64MCExpr::VK_G2; 00122 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1) 00123 RefFlags |= AArch64MCExpr::VK_G1; 00124 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0) 00125 RefFlags |= AArch64MCExpr::VK_G0; 00126 00127 if (MO.getTargetFlags() & AArch64II::MO_NC) 00128 RefFlags |= AArch64MCExpr::VK_NC; 00129 00130 const MCExpr *Expr = 00131 MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, Ctx); 00132 if (!MO.isJTI() && MO.getOffset()) 00133 Expr = MCBinaryExpr::CreateAdd( 00134 Expr, MCConstantExpr::Create(MO.getOffset(), Ctx), Ctx); 00135 00136 AArch64MCExpr::VariantKind RefKind; 00137 RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags); 00138 Expr = AArch64MCExpr::Create(Expr, RefKind, Ctx); 00139 00140 return MCOperand::CreateExpr(Expr); 00141 } 00142 00143 MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO, 00144 MCSymbol *Sym) const { 00145 if (TargetTriple.isOSDarwin()) 00146 return lowerSymbolOperandDarwin(MO, Sym); 00147 00148 assert(TargetTriple.isOSBinFormatELF() && "Expect Darwin or ELF target"); 00149 return lowerSymbolOperandELF(MO, Sym); 00150 } 00151 00152 bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO, 00153 MCOperand &MCOp) const { 00154 switch (MO.getType()) { 00155 default: 00156 llvm_unreachable("unknown operand type"); 00157 case MachineOperand::MO_Register: 00158 // Ignore all implicit register operands. 00159 if (MO.isImplicit()) 00160 return false; 00161 MCOp = MCOperand::CreateReg(MO.getReg()); 00162 break; 00163 case MachineOperand::MO_RegisterMask: 00164 // Regmasks are like implicit defs. 00165 return false; 00166 case MachineOperand::MO_Immediate: 00167 MCOp = MCOperand::CreateImm(MO.getImm()); 00168 break; 00169 case MachineOperand::MO_MachineBasicBlock: 00170 MCOp = MCOperand::CreateExpr( 00171 MCSymbolRefExpr::Create(MO.getMBB()->getSymbol(), Ctx)); 00172 break; 00173 case MachineOperand::MO_GlobalAddress: 00174 MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); 00175 break; 00176 case MachineOperand::MO_ExternalSymbol: 00177 MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); 00178 break; 00179 case MachineOperand::MO_JumpTableIndex: 00180 MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex())); 00181 break; 00182 case MachineOperand::MO_ConstantPoolIndex: 00183 MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex())); 00184 break; 00185 case MachineOperand::MO_BlockAddress: 00186 MCOp = LowerSymbolOperand( 00187 MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress())); 00188 break; 00189 } 00190 return true; 00191 } 00192 00193 void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 00194 OutMI.setOpcode(MI->getOpcode()); 00195 00196 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 00197 MCOperand MCOp; 00198 if (lowerOperand(MI->getOperand(i), MCOp)) 00199 OutMI.addOperand(MCOp); 00200 } 00201 }