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