LLVM API Documentation

AArch64MCInstLower.cpp
Go to the documentation of this file.
00001 //==-- AArch64MCInstLower.cpp - Convert AArch64 MachineInstr to an MCInst --==//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file contains code to lower AArch64 MachineInstrs to their corresponding
00011 // MCInst records.
00012 //
00013 //===----------------------------------------------------------------------===//
00014 
00015 #include "AArch64MCInstLower.h"
00016 #include "MCTargetDesc/AArch64MCExpr.h"
00017 #include "Utils/AArch64BaseInfo.h"
00018 #include "llvm/CodeGen/AsmPrinter.h"
00019 #include "llvm/CodeGen/MachineBasicBlock.h"
00020 #include "llvm/CodeGen/MachineInstr.h"
00021 #include "llvm/IR/Mangler.h"
00022 #include "llvm/MC/MCExpr.h"
00023 #include "llvm/MC/MCInst.h"
00024 #include "llvm/Support/CodeGen.h"
00025 #include "llvm/Target/TargetMachine.h"
00026 using namespace llvm;
00027 
00028 AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
00029     : Ctx(ctx), Printer(printer), TargetTriple(printer.getTargetTriple()) {}
00030 
00031 MCSymbol *
00032 AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
00033   return Printer.getSymbol(MO.getGlobal());
00034 }
00035 
00036 MCSymbol *
00037 AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
00038   return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
00039 }
00040 
00041 MCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO,
00042                                                        MCSymbol *Sym) const {
00043   // FIXME: We would like an efficient form for this, so we don't have to do a
00044   // lot of extra uniquing.
00045   MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None;
00046   if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) {
00047     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
00048       RefKind = MCSymbolRefExpr::VK_GOTPAGE;
00049     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
00050              AArch64II::MO_PAGEOFF)
00051       RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF;
00052     else
00053       llvm_unreachable("Unexpected target flags with MO_GOT on GV operand");
00054   } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) {
00055     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
00056       RefKind = MCSymbolRefExpr::VK_TLVPPAGE;
00057     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
00058              AArch64II::MO_PAGEOFF)
00059       RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF;
00060     else
00061       llvm_unreachable("Unexpected target flags with MO_TLS on GV operand");
00062   } else {
00063     if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
00064       RefKind = MCSymbolRefExpr::VK_PAGE;
00065     else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
00066              AArch64II::MO_PAGEOFF)
00067       RefKind = MCSymbolRefExpr::VK_PAGEOFF;
00068   }
00069   const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, RefKind, Ctx);
00070   if (!MO.isJTI() && MO.getOffset())
00071     Expr = MCBinaryExpr::CreateAdd(
00072         Expr, MCConstantExpr::Create(MO.getOffset(), Ctx), Ctx);
00073   return MCOperand::CreateExpr(Expr);
00074 }
00075 
00076 MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO,
00077                                                     MCSymbol *Sym) const {
00078   uint32_t RefFlags = 0;
00079 
00080   if (MO.getTargetFlags() & AArch64II::MO_GOT)
00081     RefFlags |= AArch64MCExpr::VK_GOT;
00082   else if (MO.getTargetFlags() & AArch64II::MO_TLS) {
00083     TLSModel::Model Model;
00084     if (MO.isGlobal()) {
00085       const GlobalValue *GV = MO.getGlobal();
00086       Model = Printer.TM.getTLSModel(GV);
00087     } else {
00088       assert(MO.isSymbol() &&
00089              StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" &&
00090              "unexpected external TLS symbol");
00091       Model = TLSModel::GeneralDynamic;
00092     }
00093     switch (Model) {
00094     case TLSModel::InitialExec:
00095       RefFlags |= AArch64MCExpr::VK_GOTTPREL;
00096       break;
00097     case TLSModel::LocalExec:
00098       RefFlags |= AArch64MCExpr::VK_TPREL;
00099       break;
00100     case TLSModel::LocalDynamic:
00101       RefFlags |= AArch64MCExpr::VK_DTPREL;
00102       break;
00103     case TLSModel::GeneralDynamic:
00104       RefFlags |= AArch64MCExpr::VK_TLSDESC;
00105       break;
00106     }
00107   } else {
00108     // No modifier means this is a generic reference, classified as absolute for
00109     // the cases where it matters (:abs_g0: etc).
00110     RefFlags |= AArch64MCExpr::VK_ABS;
00111   }
00112 
00113   if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE)
00114     RefFlags |= AArch64MCExpr::VK_PAGE;
00115   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) ==
00116            AArch64II::MO_PAGEOFF)
00117     RefFlags |= AArch64MCExpr::VK_PAGEOFF;
00118   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3)
00119     RefFlags |= AArch64MCExpr::VK_G3;
00120   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2)
00121     RefFlags |= AArch64MCExpr::VK_G2;
00122   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1)
00123     RefFlags |= AArch64MCExpr::VK_G1;
00124   else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0)
00125     RefFlags |= AArch64MCExpr::VK_G0;
00126 
00127   if (MO.getTargetFlags() & AArch64II::MO_NC)
00128     RefFlags |= AArch64MCExpr::VK_NC;
00129 
00130   const MCExpr *Expr =
00131       MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, Ctx);
00132   if (!MO.isJTI() && MO.getOffset())
00133     Expr = MCBinaryExpr::CreateAdd(
00134         Expr, MCConstantExpr::Create(MO.getOffset(), Ctx), Ctx);
00135 
00136   AArch64MCExpr::VariantKind RefKind;
00137   RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags);
00138   Expr = AArch64MCExpr::Create(Expr, RefKind, Ctx);
00139 
00140   return MCOperand::CreateExpr(Expr);
00141 }
00142 
00143 MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO,
00144                                                  MCSymbol *Sym) const {
00145   if (TargetTriple.isOSDarwin())
00146     return lowerSymbolOperandDarwin(MO, Sym);
00147 
00148   assert(TargetTriple.isOSBinFormatELF() && "Expect Darwin or ELF target");
00149   return lowerSymbolOperandELF(MO, Sym);
00150 }
00151 
00152 bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO,
00153                                       MCOperand &MCOp) const {
00154   switch (MO.getType()) {
00155   default:
00156     llvm_unreachable("unknown operand type");
00157   case MachineOperand::MO_Register:
00158     // Ignore all implicit register operands.
00159     if (MO.isImplicit())
00160       return false;
00161     MCOp = MCOperand::CreateReg(MO.getReg());
00162     break;
00163   case MachineOperand::MO_RegisterMask:
00164     // Regmasks are like implicit defs.
00165     return false;
00166   case MachineOperand::MO_Immediate:
00167     MCOp = MCOperand::CreateImm(MO.getImm());
00168     break;
00169   case MachineOperand::MO_MachineBasicBlock:
00170     MCOp = MCOperand::CreateExpr(
00171         MCSymbolRefExpr::Create(MO.getMBB()->getSymbol(), Ctx));
00172     break;
00173   case MachineOperand::MO_GlobalAddress:
00174     MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
00175     break;
00176   case MachineOperand::MO_ExternalSymbol:
00177     MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
00178     break;
00179   case MachineOperand::MO_JumpTableIndex:
00180     MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex()));
00181     break;
00182   case MachineOperand::MO_ConstantPoolIndex:
00183     MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex()));
00184     break;
00185   case MachineOperand::MO_BlockAddress:
00186     MCOp = LowerSymbolOperand(
00187         MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress()));
00188     break;
00189   }
00190   return true;
00191 }
00192 
00193 void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
00194   OutMI.setOpcode(MI->getOpcode());
00195 
00196   for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
00197     MCOperand MCOp;
00198     if (lowerOperand(MI->getOperand(i), MCOp))
00199       OutMI.addOperand(MCOp);
00200   }
00201 }