AArch64MCInstLower.cpp revision 280031
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" 25276479Sdim#include "llvm/Target/TargetMachine.h" 26249259Sdimusing namespace llvm; 27249259Sdim 28280031SdimAArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer) 29276479Sdim : Ctx(ctx), Printer(printer), TargetTriple(printer.getTargetTriple()) {} 30249259Sdim 31276479SdimMCSymbol * 32276479SdimAArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const { 33276479Sdim return Printer.getSymbol(MO.getGlobal()); 34276479Sdim} 35249259Sdim 36276479SdimMCSymbol * 37276479SdimAArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const { 38276479Sdim return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); 39276479Sdim} 40276479Sdim 41276479SdimMCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO, 42276479Sdim MCSymbol *Sym) const { 43276479Sdim // FIXME: We would like an efficient form for this, so we don't have to do a 44276479Sdim // lot of extra uniquing. 45276479Sdim MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 46276479Sdim if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) { 47276479Sdim if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 48276479Sdim RefKind = MCSymbolRefExpr::VK_GOTPAGE; 49276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 50276479Sdim AArch64II::MO_PAGEOFF) 51276479Sdim RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF; 52276479Sdim else 53276479Sdim llvm_unreachable("Unexpected target flags with MO_GOT on GV operand"); 54276479Sdim } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) { 55276479Sdim if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 56276479Sdim RefKind = MCSymbolRefExpr::VK_TLVPPAGE; 57276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 58276479Sdim AArch64II::MO_PAGEOFF) 59276479Sdim RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF; 60276479Sdim else 61276479Sdim llvm_unreachable("Unexpected target flags with MO_TLS on GV operand"); 62276479Sdim } else { 63276479Sdim if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 64276479Sdim RefKind = MCSymbolRefExpr::VK_PAGE; 65276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 66276479Sdim AArch64II::MO_PAGEOFF) 67276479Sdim RefKind = MCSymbolRefExpr::VK_PAGEOFF; 68249259Sdim } 69276479Sdim const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, RefKind, Ctx); 70276479Sdim if (!MO.isJTI() && MO.getOffset()) 71276479Sdim Expr = MCBinaryExpr::CreateAdd( 72276479Sdim Expr, MCConstantExpr::Create(MO.getOffset(), Ctx), Ctx); 73276479Sdim return MCOperand::CreateExpr(Expr); 74276479Sdim} 75249259Sdim 76276479SdimMCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO, 77276479Sdim MCSymbol *Sym) const { 78276479Sdim uint32_t RefFlags = 0; 79276479Sdim 80276479Sdim if (MO.getTargetFlags() & AArch64II::MO_GOT) 81276479Sdim RefFlags |= AArch64MCExpr::VK_GOT; 82276479Sdim else if (MO.getTargetFlags() & AArch64II::MO_TLS) { 83276479Sdim TLSModel::Model Model; 84276479Sdim if (MO.isGlobal()) { 85276479Sdim const GlobalValue *GV = MO.getGlobal(); 86276479Sdim Model = Printer.TM.getTLSModel(GV); 87276479Sdim } else { 88276479Sdim assert(MO.isSymbol() && 89276479Sdim StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" && 90276479Sdim "unexpected external TLS symbol"); 91276479Sdim Model = TLSModel::GeneralDynamic; 92276479Sdim } 93276479Sdim switch (Model) { 94276479Sdim case TLSModel::InitialExec: 95276479Sdim RefFlags |= AArch64MCExpr::VK_GOTTPREL; 96276479Sdim break; 97276479Sdim case TLSModel::LocalExec: 98276479Sdim RefFlags |= AArch64MCExpr::VK_TPREL; 99276479Sdim break; 100276479Sdim case TLSModel::LocalDynamic: 101276479Sdim RefFlags |= AArch64MCExpr::VK_DTPREL; 102276479Sdim break; 103276479Sdim case TLSModel::GeneralDynamic: 104276479Sdim RefFlags |= AArch64MCExpr::VK_TLSDESC; 105276479Sdim break; 106276479Sdim } 107276479Sdim } else { 108276479Sdim // No modifier means this is a generic reference, classified as absolute for 109276479Sdim // the cases where it matters (:abs_g0: etc). 110276479Sdim RefFlags |= AArch64MCExpr::VK_ABS; 111276479Sdim } 112276479Sdim 113276479Sdim if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 114276479Sdim RefFlags |= AArch64MCExpr::VK_PAGE; 115276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 116276479Sdim AArch64II::MO_PAGEOFF) 117276479Sdim RefFlags |= AArch64MCExpr::VK_PAGEOFF; 118276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3) 119276479Sdim RefFlags |= AArch64MCExpr::VK_G3; 120276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2) 121276479Sdim RefFlags |= AArch64MCExpr::VK_G2; 122276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1) 123276479Sdim RefFlags |= AArch64MCExpr::VK_G1; 124276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0) 125276479Sdim RefFlags |= AArch64MCExpr::VK_G0; 126276479Sdim 127276479Sdim if (MO.getTargetFlags() & AArch64II::MO_NC) 128276479Sdim RefFlags |= AArch64MCExpr::VK_NC; 129276479Sdim 130276479Sdim const MCExpr *Expr = 131276479Sdim MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, Ctx); 132249259Sdim if (!MO.isJTI() && MO.getOffset()) 133276479Sdim Expr = MCBinaryExpr::CreateAdd( 134276479Sdim Expr, MCConstantExpr::Create(MO.getOffset(), Ctx), Ctx); 135249259Sdim 136276479Sdim AArch64MCExpr::VariantKind RefKind; 137276479Sdim RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags); 138276479Sdim Expr = AArch64MCExpr::Create(Expr, RefKind, Ctx); 139276479Sdim 140249259Sdim return MCOperand::CreateExpr(Expr); 141249259Sdim} 142249259Sdim 143276479SdimMCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO, 144276479Sdim MCSymbol *Sym) const { 145276479Sdim if (TargetTriple.isOSDarwin()) 146276479Sdim return lowerSymbolOperandDarwin(MO, Sym); 147276479Sdim 148276479Sdim assert(TargetTriple.isOSBinFormatELF() && "Expect Darwin or ELF target"); 149276479Sdim return lowerSymbolOperandELF(MO, Sym); 150276479Sdim} 151276479Sdim 152276479Sdimbool AArch64MCInstLower::lowerOperand(const MachineOperand &MO, 153276479Sdim MCOperand &MCOp) const { 154249259Sdim switch (MO.getType()) { 155276479Sdim default: 156276479Sdim llvm_unreachable("unknown operand type"); 157249259Sdim case MachineOperand::MO_Register: 158276479Sdim // Ignore all implicit register operands. 159249259Sdim if (MO.isImplicit()) 160249259Sdim return false; 161249259Sdim MCOp = MCOperand::CreateReg(MO.getReg()); 162249259Sdim break; 163276479Sdim case MachineOperand::MO_RegisterMask: 164276479Sdim // Regmasks are like implicit defs. 165276479Sdim return false; 166249259Sdim case MachineOperand::MO_Immediate: 167249259Sdim MCOp = MCOperand::CreateImm(MO.getImm()); 168249259Sdim break; 169276479Sdim case MachineOperand::MO_MachineBasicBlock: 170276479Sdim MCOp = MCOperand::CreateExpr( 171276479Sdim MCSymbolRefExpr::Create(MO.getMBB()->getSymbol(), Ctx)); 172261991Sdim break; 173276479Sdim case MachineOperand::MO_GlobalAddress: 174276479Sdim MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); 175249259Sdim break; 176249259Sdim case MachineOperand::MO_ExternalSymbol: 177276479Sdim MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); 178249259Sdim break; 179249259Sdim case MachineOperand::MO_JumpTableIndex: 180276479Sdim MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex())); 181249259Sdim break; 182249259Sdim case MachineOperand::MO_ConstantPoolIndex: 183276479Sdim MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex())); 184249259Sdim break; 185276479Sdim case MachineOperand::MO_BlockAddress: 186276479Sdim MCOp = LowerSymbolOperand( 187276479Sdim MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress())); 188276479Sdim break; 189249259Sdim } 190249259Sdim return true; 191249259Sdim} 192249259Sdim 193276479Sdimvoid AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 194249259Sdim OutMI.setOpcode(MI->getOpcode()); 195249259Sdim 196249259Sdim for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { 197249259Sdim MCOperand MCOp; 198276479Sdim if (lowerOperand(MI->getOperand(i), MCOp)) 199249259Sdim OutMI.addOperand(MCOp); 200249259Sdim } 201249259Sdim} 202