1276479Sdim//==-- AArch64MCInstLower.cpp - Convert AArch64 MachineInstr to an MCInst --==// 2249259Sdim// 3249259Sdim// The LLVM Compiler Infrastructure 4249259Sdim// 5249259Sdim// This file is distributed under the University of Illinois Open Source 6249259Sdim// License. See LICENSE.TXT for details. 7249259Sdim// 8249259Sdim//===----------------------------------------------------------------------===// 9249259Sdim// 10249259Sdim// This file contains code to lower AArch64 MachineInstrs to their corresponding 11249259Sdim// MCInst records. 12249259Sdim// 13249259Sdim//===----------------------------------------------------------------------===// 14249259Sdim 15276479Sdim#include "AArch64MCInstLower.h" 16249259Sdim#include "MCTargetDesc/AArch64MCExpr.h" 17249259Sdim#include "Utils/AArch64BaseInfo.h" 18249259Sdim#include "llvm/CodeGen/AsmPrinter.h" 19276479Sdim#include "llvm/CodeGen/MachineBasicBlock.h" 20276479Sdim#include "llvm/CodeGen/MachineInstr.h" 21276479Sdim#include "llvm/IR/Mangler.h" 22249259Sdim#include "llvm/MC/MCExpr.h" 23249259Sdim#include "llvm/MC/MCInst.h" 24276479Sdim#include "llvm/Support/CodeGen.h" 25280865Semaste#include "llvm/Support/CommandLine.h" 26276479Sdim#include "llvm/Target/TargetMachine.h" 27249259Sdimusing namespace llvm; 28249259Sdim 29280865Semasteextern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration; 30280865Semaste 31280031SdimAArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer) 32276479Sdim : Ctx(ctx), Printer(printer), TargetTriple(printer.getTargetTriple()) {} 33249259Sdim 34276479SdimMCSymbol * 35276479SdimAArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const { 36276479Sdim return Printer.getSymbol(MO.getGlobal()); 37276479Sdim} 38249259Sdim 39276479SdimMCSymbol * 40276479SdimAArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const { 41276479Sdim return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); 42276479Sdim} 43276479Sdim 44276479SdimMCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO, 45276479Sdim MCSymbol *Sym) const { 46276479Sdim // FIXME: We would like an efficient form for this, so we don't have to do a 47276479Sdim // lot of extra uniquing. 48276479Sdim MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 49276479Sdim if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) { 50276479Sdim if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 51276479Sdim RefKind = MCSymbolRefExpr::VK_GOTPAGE; 52276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 53276479Sdim AArch64II::MO_PAGEOFF) 54276479Sdim RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF; 55276479Sdim else 56276479Sdim llvm_unreachable("Unexpected target flags with MO_GOT on GV operand"); 57276479Sdim } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) { 58276479Sdim if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 59276479Sdim RefKind = MCSymbolRefExpr::VK_TLVPPAGE; 60276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 61276479Sdim AArch64II::MO_PAGEOFF) 62276479Sdim RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF; 63276479Sdim else 64276479Sdim llvm_unreachable("Unexpected target flags with MO_TLS on GV operand"); 65276479Sdim } else { 66276479Sdim if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 67276479Sdim RefKind = MCSymbolRefExpr::VK_PAGE; 68276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 69276479Sdim AArch64II::MO_PAGEOFF) 70276479Sdim RefKind = MCSymbolRefExpr::VK_PAGEOFF; 71249259Sdim } 72288943Sdim const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx); 73276479Sdim if (!MO.isJTI() && MO.getOffset()) 74288943Sdim Expr = MCBinaryExpr::createAdd( 75288943Sdim Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 76288943Sdim return MCOperand::createExpr(Expr); 77276479Sdim} 78249259Sdim 79276479SdimMCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO, 80276479Sdim MCSymbol *Sym) const { 81276479Sdim uint32_t RefFlags = 0; 82276479Sdim 83276479Sdim if (MO.getTargetFlags() & AArch64II::MO_GOT) 84276479Sdim RefFlags |= AArch64MCExpr::VK_GOT; 85276479Sdim else if (MO.getTargetFlags() & AArch64II::MO_TLS) { 86276479Sdim TLSModel::Model Model; 87276479Sdim if (MO.isGlobal()) { 88276479Sdim const GlobalValue *GV = MO.getGlobal(); 89276479Sdim Model = Printer.TM.getTLSModel(GV); 90280865Semaste if (!EnableAArch64ELFLocalDynamicTLSGeneration && 91280865Semaste Model == TLSModel::LocalDynamic) 92280865Semaste Model = TLSModel::GeneralDynamic; 93280865Semaste 94276479Sdim } else { 95276479Sdim assert(MO.isSymbol() && 96276479Sdim StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" && 97276479Sdim "unexpected external TLS symbol"); 98280865Semaste // The general dynamic access sequence is used to get the 99280865Semaste // address of _TLS_MODULE_BASE_. 100276479Sdim Model = TLSModel::GeneralDynamic; 101276479Sdim } 102276479Sdim switch (Model) { 103276479Sdim case TLSModel::InitialExec: 104276479Sdim RefFlags |= AArch64MCExpr::VK_GOTTPREL; 105276479Sdim break; 106276479Sdim case TLSModel::LocalExec: 107276479Sdim RefFlags |= AArch64MCExpr::VK_TPREL; 108276479Sdim break; 109276479Sdim case TLSModel::LocalDynamic: 110276479Sdim RefFlags |= AArch64MCExpr::VK_DTPREL; 111276479Sdim break; 112276479Sdim case TLSModel::GeneralDynamic: 113276479Sdim RefFlags |= AArch64MCExpr::VK_TLSDESC; 114276479Sdim break; 115276479Sdim } 116276479Sdim } else { 117276479Sdim // No modifier means this is a generic reference, classified as absolute for 118276479Sdim // the cases where it matters (:abs_g0: etc). 119276479Sdim RefFlags |= AArch64MCExpr::VK_ABS; 120276479Sdim } 121276479Sdim 122276479Sdim if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 123276479Sdim RefFlags |= AArch64MCExpr::VK_PAGE; 124276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 125276479Sdim AArch64II::MO_PAGEOFF) 126276479Sdim RefFlags |= AArch64MCExpr::VK_PAGEOFF; 127276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3) 128276479Sdim RefFlags |= AArch64MCExpr::VK_G3; 129276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2) 130276479Sdim RefFlags |= AArch64MCExpr::VK_G2; 131276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1) 132276479Sdim RefFlags |= AArch64MCExpr::VK_G1; 133276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0) 134276479Sdim RefFlags |= AArch64MCExpr::VK_G0; 135280865Semaste else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12) 136280865Semaste RefFlags |= AArch64MCExpr::VK_HI12; 137276479Sdim 138276479Sdim if (MO.getTargetFlags() & AArch64II::MO_NC) 139276479Sdim RefFlags |= AArch64MCExpr::VK_NC; 140276479Sdim 141276479Sdim const MCExpr *Expr = 142288943Sdim MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); 143249259Sdim if (!MO.isJTI() && MO.getOffset()) 144288943Sdim Expr = MCBinaryExpr::createAdd( 145288943Sdim Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 146249259Sdim 147276479Sdim AArch64MCExpr::VariantKind RefKind; 148276479Sdim RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags); 149288943Sdim Expr = AArch64MCExpr::create(Expr, RefKind, Ctx); 150276479Sdim 151288943Sdim return MCOperand::createExpr(Expr); 152249259Sdim} 153249259Sdim 154276479SdimMCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO, 155276479Sdim MCSymbol *Sym) const { 156276479Sdim if (TargetTriple.isOSDarwin()) 157276479Sdim return lowerSymbolOperandDarwin(MO, Sym); 158276479Sdim 159276479Sdim assert(TargetTriple.isOSBinFormatELF() && "Expect Darwin or ELF target"); 160276479Sdim return lowerSymbolOperandELF(MO, Sym); 161276479Sdim} 162276479Sdim 163276479Sdimbool AArch64MCInstLower::lowerOperand(const MachineOperand &MO, 164276479Sdim MCOperand &MCOp) const { 165249259Sdim switch (MO.getType()) { 166276479Sdim default: 167276479Sdim llvm_unreachable("unknown operand type"); 168249259Sdim case MachineOperand::MO_Register: 169276479Sdim // Ignore all implicit register operands. 170249259Sdim if (MO.isImplicit()) 171249259Sdim return false; 172288943Sdim MCOp = MCOperand::createReg(MO.getReg()); 173249259Sdim break; 174276479Sdim case MachineOperand::MO_RegisterMask: 175276479Sdim // Regmasks are like implicit defs. 176276479Sdim return false; 177249259Sdim case MachineOperand::MO_Immediate: 178288943Sdim MCOp = MCOperand::createImm(MO.getImm()); 179249259Sdim break; 180276479Sdim case MachineOperand::MO_MachineBasicBlock: 181288943Sdim MCOp = MCOperand::createExpr( 182288943Sdim MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx)); 183261991Sdim break; 184276479Sdim case MachineOperand::MO_GlobalAddress: 185276479Sdim MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); 186249259Sdim break; 187249259Sdim case MachineOperand::MO_ExternalSymbol: 188276479Sdim MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); 189249259Sdim break; 190288943Sdim case MachineOperand::MO_MCSymbol: 191288943Sdim MCOp = LowerSymbolOperand(MO, MO.getMCSymbol()); 192288943Sdim break; 193249259Sdim case MachineOperand::MO_JumpTableIndex: 194276479Sdim MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex())); 195249259Sdim break; 196249259Sdim case MachineOperand::MO_ConstantPoolIndex: 197276479Sdim MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex())); 198249259Sdim break; 199276479Sdim case MachineOperand::MO_BlockAddress: 200276479Sdim MCOp = LowerSymbolOperand( 201276479Sdim MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress())); 202276479Sdim break; 203249259Sdim } 204249259Sdim return true; 205249259Sdim} 206249259Sdim 207276479Sdimvoid AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 208249259Sdim OutMI.setOpcode(MI->getOpcode()); 209249259Sdim 210296417Sdim for (const MachineOperand &MO : MI->operands()) { 211249259Sdim MCOperand MCOp; 212296417Sdim if (lowerOperand(MO, MCOp)) 213249259Sdim OutMI.addOperand(MCOp); 214249259Sdim } 215249259Sdim} 216