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/MCContext.h" 23 #include "llvm/MC/MCExpr.h" 24 #include "llvm/MC/MCInst.h" 25 #include "llvm/Support/CodeGen.h" 26 #include "llvm/Support/CommandLine.h" 27 #include "llvm/Target/TargetLoweringObjectFile.h" 28 #include "llvm/Target/TargetMachine.h" 29 using namespace llvm; 30 31 extern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration; 32 33 AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer) 34 : Ctx(ctx), Printer(printer) {} 35 36 MCSymbol * 37 AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const { 38 const GlobalValue *GV = MO.getGlobal(); 39 unsigned TargetFlags = MO.getTargetFlags(); 40 const Triple &TheTriple = Printer.TM.getTargetTriple(); 41 if (!TheTriple.isOSBinFormatCOFF()) 42 return Printer.getSymbol(GV); 43 44 assert(TheTriple.isOSWindows() && 45 "Windows is the only supported COFF target"); 46 47 bool IsIndirect = (TargetFlags & AArch64II::MO_DLLIMPORT); 48 if (!IsIndirect) 49 return Printer.getSymbol(GV); 50 51 SmallString<128> Name; 52 Name = "__imp_"; 53 Printer.TM.getNameWithPrefix(Name, GV, 54 Printer.getObjFileLowering().getMangler()); 55 56 return Ctx.getOrCreateSymbol(Name); 57 } 58 59 MCSymbol * 60 AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const { 61 return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); 62 } 63 64 MCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO, 65 MCSymbol *Sym) const { 66 // FIXME: We would like an efficient form for this, so we don't have to do a 67 // lot of extra uniquing. 68 MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 69 if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) { 70 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 71 RefKind = MCSymbolRefExpr::VK_GOTPAGE; 72 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 73 AArch64II::MO_PAGEOFF) 74 RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF; 75 else 76 llvm_unreachable("Unexpected target flags with MO_GOT on GV operand"); 77 } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) { 78 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 79 RefKind = MCSymbolRefExpr::VK_TLVPPAGE; 80 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 81 AArch64II::MO_PAGEOFF) 82 RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF; 83 else 84 llvm_unreachable("Unexpected target flags with MO_TLS on GV operand"); 85 } else { 86 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 87 RefKind = MCSymbolRefExpr::VK_PAGE; 88 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 89 AArch64II::MO_PAGEOFF) 90 RefKind = MCSymbolRefExpr::VK_PAGEOFF; 91 } 92 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx); 93 if (!MO.isJTI() && MO.getOffset()) 94 Expr = MCBinaryExpr::createAdd( 95 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 96 return MCOperand::createExpr(Expr); 97 } 98 99 MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO, 100 MCSymbol *Sym) const { 101 uint32_t RefFlags = 0; 102 103 if (MO.getTargetFlags() & AArch64II::MO_GOT) 104 RefFlags |= AArch64MCExpr::VK_GOT; 105 else if (MO.getTargetFlags() & AArch64II::MO_TLS) { 106 TLSModel::Model Model; 107 if (MO.isGlobal()) { 108 const GlobalValue *GV = MO.getGlobal(); 109 Model = Printer.TM.getTLSModel(GV); 110 if (!EnableAArch64ELFLocalDynamicTLSGeneration && 111 Model == TLSModel::LocalDynamic) 112 Model = TLSModel::GeneralDynamic; 113 114 } else { 115 assert(MO.isSymbol() && 116 StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" && 117 "unexpected external TLS symbol"); 118 // The general dynamic access sequence is used to get the 119 // address of _TLS_MODULE_BASE_. 120 Model = TLSModel::GeneralDynamic; 121 } 122 switch (Model) { 123 case TLSModel::InitialExec: 124 RefFlags |= AArch64MCExpr::VK_GOTTPREL; 125 break; 126 case TLSModel::LocalExec: 127 RefFlags |= AArch64MCExpr::VK_TPREL; 128 break; 129 case TLSModel::LocalDynamic: 130 RefFlags |= AArch64MCExpr::VK_DTPREL; 131 break; 132 case TLSModel::GeneralDynamic: 133 RefFlags |= AArch64MCExpr::VK_TLSDESC; 134 break; 135 } 136 } else { 137 // No modifier means this is a generic reference, classified as absolute for 138 // the cases where it matters (:abs_g0: etc). 139 RefFlags |= AArch64MCExpr::VK_ABS; 140 } 141 142 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 143 RefFlags |= AArch64MCExpr::VK_PAGE; 144 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 145 AArch64II::MO_PAGEOFF) 146 RefFlags |= AArch64MCExpr::VK_PAGEOFF; 147 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3) 148 RefFlags |= AArch64MCExpr::VK_G3; 149 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2) 150 RefFlags |= AArch64MCExpr::VK_G2; 151 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1) 152 RefFlags |= AArch64MCExpr::VK_G1; 153 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0) 154 RefFlags |= AArch64MCExpr::VK_G0; 155 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12) 156 RefFlags |= AArch64MCExpr::VK_HI12; 157 158 if (MO.getTargetFlags() & AArch64II::MO_NC) 159 RefFlags |= AArch64MCExpr::VK_NC; 160 161 const MCExpr *Expr = 162 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); 163 if (!MO.isJTI() && MO.getOffset()) 164 Expr = MCBinaryExpr::createAdd( 165 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 166 167 AArch64MCExpr::VariantKind RefKind; 168 RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags); 169 Expr = AArch64MCExpr::create(Expr, RefKind, Ctx); 170 171 return MCOperand::createExpr(Expr); 172 } 173 174 MCOperand AArch64MCInstLower::lowerSymbolOperandCOFF(const MachineOperand &MO, 175 MCSymbol *Sym) const { 176 AArch64MCExpr::VariantKind RefKind = AArch64MCExpr::VK_NONE; 177 if (MO.getTargetFlags() & AArch64II::MO_TLS) { 178 if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGEOFF) 179 RefKind = AArch64MCExpr::VK_SECREL_LO12; 180 else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 181 AArch64II::MO_HI12) 182 RefKind = AArch64MCExpr::VK_SECREL_HI12; 183 } 184 const MCExpr *Expr = 185 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); 186 if (!MO.isJTI() && MO.getOffset()) 187 Expr = MCBinaryExpr::createAdd( 188 Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 189 Expr = AArch64MCExpr::create(Expr, RefKind, Ctx); 190 return MCOperand::createExpr(Expr); 191 } 192 193 MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO, 194 MCSymbol *Sym) const { 195 if (Printer.TM.getTargetTriple().isOSDarwin()) 196 return lowerSymbolOperandDarwin(MO, Sym); 197 if (Printer.TM.getTargetTriple().isOSBinFormatCOFF()) 198 return lowerSymbolOperandCOFF(MO, Sym); 199 200 assert(Printer.TM.getTargetTriple().isOSBinFormatELF() && "Invalid target"); 201 return lowerSymbolOperandELF(MO, Sym); 202 } 203 204 bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO, 205 MCOperand &MCOp) const { 206 switch (MO.getType()) { 207 default: 208 llvm_unreachable("unknown operand type"); 209 case MachineOperand::MO_Register: 210 // Ignore all implicit register operands. 211 if (MO.isImplicit()) 212 return false; 213 MCOp = MCOperand::createReg(MO.getReg()); 214 break; 215 case MachineOperand::MO_RegisterMask: 216 // Regmasks are like implicit defs. 217 return false; 218 case MachineOperand::MO_Immediate: 219 MCOp = MCOperand::createImm(MO.getImm()); 220 break; 221 case MachineOperand::MO_MachineBasicBlock: 222 MCOp = MCOperand::createExpr( 223 MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx)); 224 break; 225 case MachineOperand::MO_GlobalAddress: 226 MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); 227 break; 228 case MachineOperand::MO_ExternalSymbol: 229 MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); 230 break; 231 case MachineOperand::MO_MCSymbol: 232 MCOp = LowerSymbolOperand(MO, MO.getMCSymbol()); 233 break; 234 case MachineOperand::MO_JumpTableIndex: 235 MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex())); 236 break; 237 case MachineOperand::MO_ConstantPoolIndex: 238 MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex())); 239 break; 240 case MachineOperand::MO_BlockAddress: 241 MCOp = LowerSymbolOperand( 242 MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress())); 243 break; 244 } 245 return true; 246 } 247 248 void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 249 OutMI.setOpcode(MI->getOpcode()); 250 251 for (const MachineOperand &MO : MI->operands()) { 252 MCOperand MCOp; 253 if (lowerOperand(MO, MCOp)) 254 OutMI.addOperand(MCOp); 255 } 256 } 257