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