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" 27using namespace llvm; 28 29extern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration; 30 31AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer) 32 : Ctx(ctx), Printer(printer), TargetTriple(printer.getTargetTriple()) {} 33 34MCSymbol * 35AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const { 36 return Printer.getSymbol(MO.getGlobal()); 37} 38 39MCSymbol * 40AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const { 41 return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); 42} 43 44MCOperand 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 79MCOperand 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 154MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO, 155 MCSymbol *Sym) const { 156 if (TargetTriple.isOSDarwin()) 157 return lowerSymbolOperandDarwin(MO, Sym); 158 159 assert(TargetTriple.isOSBinFormatELF() && "Expect Darwin or ELF target"); 160 return lowerSymbolOperandELF(MO, Sym); 161} 162 163bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO, 164 MCOperand &MCOp) const { 165 switch (MO.getType()) { 166 default: 167 llvm_unreachable("unknown operand type"); 168 case MachineOperand::MO_Register: 169 // Ignore all implicit register operands. 170 if (MO.isImplicit()) 171 return false; 172 MCOp = MCOperand::createReg(MO.getReg()); 173 break; 174 case MachineOperand::MO_RegisterMask: 175 // Regmasks are like implicit defs. 176 return false; 177 case MachineOperand::MO_Immediate: 178 MCOp = MCOperand::createImm(MO.getImm()); 179 break; 180 case MachineOperand::MO_MachineBasicBlock: 181 MCOp = MCOperand::createExpr( 182 MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx)); 183 break; 184 case MachineOperand::MO_GlobalAddress: 185 MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); 186 break; 187 case MachineOperand::MO_ExternalSymbol: 188 MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); 189 break; 190 case MachineOperand::MO_MCSymbol: 191 MCOp = LowerSymbolOperand(MO, MO.getMCSymbol()); 192 break; 193 case MachineOperand::MO_JumpTableIndex: 194 MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex())); 195 break; 196 case MachineOperand::MO_ConstantPoolIndex: 197 MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex())); 198 break; 199 case MachineOperand::MO_BlockAddress: 200 MCOp = LowerSymbolOperand( 201 MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress())); 202 break; 203 } 204 return true; 205} 206 207void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 208 OutMI.setOpcode(MI->getOpcode()); 209 210 for (const MachineOperand &MO : MI->operands()) { 211 MCOperand MCOp; 212 if (lowerOperand(MO, MCOp)) 213 OutMI.addOperand(MCOp); 214 } 215} 216