1276479Sdim//==-- AArch64MCInstLower.cpp - Convert AArch64 MachineInstr to an MCInst --==// 2249259Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6249259Sdim// 7249259Sdim//===----------------------------------------------------------------------===// 8249259Sdim// 9249259Sdim// This file contains code to lower AArch64 MachineInstrs to their corresponding 10249259Sdim// MCInst records. 11249259Sdim// 12249259Sdim//===----------------------------------------------------------------------===// 13249259Sdim 14276479Sdim#include "AArch64MCInstLower.h" 15249259Sdim#include "MCTargetDesc/AArch64MCExpr.h" 16249259Sdim#include "Utils/AArch64BaseInfo.h" 17249259Sdim#include "llvm/CodeGen/AsmPrinter.h" 18276479Sdim#include "llvm/CodeGen/MachineBasicBlock.h" 19276479Sdim#include "llvm/CodeGen/MachineInstr.h" 20344779Sdim#include "llvm/CodeGen/MachineModuleInfoImpls.h" 21276479Sdim#include "llvm/IR/Mangler.h" 22327952Sdim#include "llvm/MC/MCContext.h" 23249259Sdim#include "llvm/MC/MCExpr.h" 24249259Sdim#include "llvm/MC/MCInst.h" 25276479Sdim#include "llvm/Support/CodeGen.h" 26280865Semaste#include "llvm/Support/CommandLine.h" 27341825Sdim#include "llvm/Target/TargetLoweringObjectFile.h" 28276479Sdim#include "llvm/Target/TargetMachine.h" 29249259Sdimusing namespace llvm; 30249259Sdim 31280865Semasteextern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration; 32280865Semaste 33280031SdimAArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer) 34314564Sdim : Ctx(ctx), Printer(printer) {} 35249259Sdim 36276479SdimMCSymbol * 37276479SdimAArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const { 38327952Sdim const GlobalValue *GV = MO.getGlobal(); 39327952Sdim unsigned TargetFlags = MO.getTargetFlags(); 40327952Sdim const Triple &TheTriple = Printer.TM.getTargetTriple(); 41327952Sdim if (!TheTriple.isOSBinFormatCOFF()) 42327952Sdim return Printer.getSymbol(GV); 43327952Sdim 44327952Sdim assert(TheTriple.isOSWindows() && 45327952Sdim "Windows is the only supported COFF target"); 46327952Sdim 47344779Sdim bool IsIndirect = (TargetFlags & (AArch64II::MO_DLLIMPORT | AArch64II::MO_COFFSTUB)); 48327952Sdim if (!IsIndirect) 49327952Sdim return Printer.getSymbol(GV); 50327952Sdim 51327952Sdim SmallString<128> Name; 52344779Sdim if (TargetFlags & AArch64II::MO_DLLIMPORT) 53344779Sdim Name = "__imp_"; 54344779Sdim else if (TargetFlags & AArch64II::MO_COFFSTUB) 55344779Sdim Name = ".refptr."; 56327952Sdim Printer.TM.getNameWithPrefix(Name, GV, 57327952Sdim Printer.getObjFileLowering().getMangler()); 58327952Sdim 59344779Sdim MCSymbol *MCSym = Ctx.getOrCreateSymbol(Name); 60344779Sdim 61344779Sdim if (TargetFlags & AArch64II::MO_COFFSTUB) { 62344779Sdim MachineModuleInfoCOFF &MMICOFF = 63344779Sdim Printer.MMI->getObjFileInfo<MachineModuleInfoCOFF>(); 64344779Sdim MachineModuleInfoImpl::StubValueTy &StubSym = 65344779Sdim MMICOFF.getGVStubEntry(MCSym); 66344779Sdim 67344779Sdim if (!StubSym.getPointer()) 68344779Sdim StubSym = MachineModuleInfoImpl::StubValueTy(Printer.getSymbol(GV), true); 69344779Sdim } 70344779Sdim 71344779Sdim return MCSym; 72276479Sdim} 73249259Sdim 74276479SdimMCSymbol * 75276479SdimAArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const { 76276479Sdim return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); 77276479Sdim} 78276479Sdim 79276479SdimMCOperand AArch64MCInstLower::lowerSymbolOperandDarwin(const MachineOperand &MO, 80276479Sdim MCSymbol *Sym) const { 81276479Sdim // FIXME: We would like an efficient form for this, so we don't have to do a 82276479Sdim // lot of extra uniquing. 83276479Sdim MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 84276479Sdim if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) { 85276479Sdim if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 86276479Sdim RefKind = MCSymbolRefExpr::VK_GOTPAGE; 87276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 88276479Sdim AArch64II::MO_PAGEOFF) 89276479Sdim RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF; 90276479Sdim else 91276479Sdim llvm_unreachable("Unexpected target flags with MO_GOT on GV operand"); 92276479Sdim } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) { 93276479Sdim if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 94276479Sdim RefKind = MCSymbolRefExpr::VK_TLVPPAGE; 95276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 96276479Sdim AArch64II::MO_PAGEOFF) 97276479Sdim RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF; 98276479Sdim else 99276479Sdim llvm_unreachable("Unexpected target flags with MO_TLS on GV operand"); 100276479Sdim } else { 101276479Sdim if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 102276479Sdim RefKind = MCSymbolRefExpr::VK_PAGE; 103276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 104276479Sdim AArch64II::MO_PAGEOFF) 105276479Sdim RefKind = MCSymbolRefExpr::VK_PAGEOFF; 106249259Sdim } 107288943Sdim const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx); 108276479Sdim if (!MO.isJTI() && MO.getOffset()) 109288943Sdim Expr = MCBinaryExpr::createAdd( 110288943Sdim Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 111288943Sdim return MCOperand::createExpr(Expr); 112276479Sdim} 113249259Sdim 114276479SdimMCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO, 115276479Sdim MCSymbol *Sym) const { 116276479Sdim uint32_t RefFlags = 0; 117276479Sdim 118276479Sdim if (MO.getTargetFlags() & AArch64II::MO_GOT) 119276479Sdim RefFlags |= AArch64MCExpr::VK_GOT; 120276479Sdim else if (MO.getTargetFlags() & AArch64II::MO_TLS) { 121276479Sdim TLSModel::Model Model; 122276479Sdim if (MO.isGlobal()) { 123276479Sdim const GlobalValue *GV = MO.getGlobal(); 124276479Sdim Model = Printer.TM.getTLSModel(GV); 125280865Semaste if (!EnableAArch64ELFLocalDynamicTLSGeneration && 126280865Semaste Model == TLSModel::LocalDynamic) 127280865Semaste Model = TLSModel::GeneralDynamic; 128280865Semaste 129276479Sdim } else { 130276479Sdim assert(MO.isSymbol() && 131276479Sdim StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" && 132276479Sdim "unexpected external TLS symbol"); 133280865Semaste // The general dynamic access sequence is used to get the 134280865Semaste // address of _TLS_MODULE_BASE_. 135276479Sdim Model = TLSModel::GeneralDynamic; 136276479Sdim } 137276479Sdim switch (Model) { 138276479Sdim case TLSModel::InitialExec: 139276479Sdim RefFlags |= AArch64MCExpr::VK_GOTTPREL; 140276479Sdim break; 141276479Sdim case TLSModel::LocalExec: 142276479Sdim RefFlags |= AArch64MCExpr::VK_TPREL; 143276479Sdim break; 144276479Sdim case TLSModel::LocalDynamic: 145276479Sdim RefFlags |= AArch64MCExpr::VK_DTPREL; 146276479Sdim break; 147276479Sdim case TLSModel::GeneralDynamic: 148276479Sdim RefFlags |= AArch64MCExpr::VK_TLSDESC; 149276479Sdim break; 150276479Sdim } 151360784Sdim } else if (MO.getTargetFlags() & AArch64II::MO_PREL) { 152360784Sdim RefFlags |= AArch64MCExpr::VK_PREL; 153276479Sdim } else { 154276479Sdim // No modifier means this is a generic reference, classified as absolute for 155276479Sdim // the cases where it matters (:abs_g0: etc). 156276479Sdim RefFlags |= AArch64MCExpr::VK_ABS; 157276479Sdim } 158276479Sdim 159276479Sdim if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 160276479Sdim RefFlags |= AArch64MCExpr::VK_PAGE; 161276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 162276479Sdim AArch64II::MO_PAGEOFF) 163276479Sdim RefFlags |= AArch64MCExpr::VK_PAGEOFF; 164276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3) 165276479Sdim RefFlags |= AArch64MCExpr::VK_G3; 166276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2) 167276479Sdim RefFlags |= AArch64MCExpr::VK_G2; 168276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1) 169276479Sdim RefFlags |= AArch64MCExpr::VK_G1; 170276479Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0) 171276479Sdim RefFlags |= AArch64MCExpr::VK_G0; 172280865Semaste else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12) 173280865Semaste RefFlags |= AArch64MCExpr::VK_HI12; 174276479Sdim 175276479Sdim if (MO.getTargetFlags() & AArch64II::MO_NC) 176276479Sdim RefFlags |= AArch64MCExpr::VK_NC; 177276479Sdim 178276479Sdim const MCExpr *Expr = 179288943Sdim MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); 180249259Sdim if (!MO.isJTI() && MO.getOffset()) 181288943Sdim Expr = MCBinaryExpr::createAdd( 182288943Sdim Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 183249259Sdim 184276479Sdim AArch64MCExpr::VariantKind RefKind; 185276479Sdim RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags); 186288943Sdim Expr = AArch64MCExpr::create(Expr, RefKind, Ctx); 187276479Sdim 188288943Sdim return MCOperand::createExpr(Expr); 189249259Sdim} 190249259Sdim 191321369SdimMCOperand AArch64MCInstLower::lowerSymbolOperandCOFF(const MachineOperand &MO, 192321369Sdim MCSymbol *Sym) const { 193344779Sdim uint32_t RefFlags = 0; 194344779Sdim 195341825Sdim if (MO.getTargetFlags() & AArch64II::MO_TLS) { 196341825Sdim if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGEOFF) 197344779Sdim RefFlags |= AArch64MCExpr::VK_SECREL_LO12; 198341825Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 199341825Sdim AArch64II::MO_HI12) 200344779Sdim RefFlags |= AArch64MCExpr::VK_SECREL_HI12; 201344779Sdim 202344779Sdim } else if (MO.getTargetFlags() & AArch64II::MO_S) { 203344779Sdim RefFlags |= AArch64MCExpr::VK_SABS; 204344779Sdim } else { 205344779Sdim RefFlags |= AArch64MCExpr::VK_ABS; 206341825Sdim } 207344779Sdim 208344779Sdim if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3) 209344779Sdim RefFlags |= AArch64MCExpr::VK_G3; 210344779Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2) 211344779Sdim RefFlags |= AArch64MCExpr::VK_G2; 212344779Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1) 213344779Sdim RefFlags |= AArch64MCExpr::VK_G1; 214344779Sdim else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0) 215344779Sdim RefFlags |= AArch64MCExpr::VK_G0; 216344779Sdim 217344779Sdim // FIXME: Currently we only set VK_NC for MO_G3/MO_G2/MO_G1/MO_G0. This is 218344779Sdim // because setting VK_NC for others would mean setting their respective 219344779Sdim // RefFlags correctly. We should do this in a separate patch. 220344779Sdim if (MO.getTargetFlags() & AArch64II::MO_NC) { 221344779Sdim auto MOFrag = (MO.getTargetFlags() & AArch64II::MO_FRAGMENT); 222344779Sdim if (MOFrag == AArch64II::MO_G3 || MOFrag == AArch64II::MO_G2 || 223344779Sdim MOFrag == AArch64II::MO_G1 || MOFrag == AArch64II::MO_G0) 224344779Sdim RefFlags |= AArch64MCExpr::VK_NC; 225344779Sdim } 226344779Sdim 227341825Sdim const MCExpr *Expr = 228341825Sdim MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); 229321369Sdim if (!MO.isJTI() && MO.getOffset()) 230321369Sdim Expr = MCBinaryExpr::createAdd( 231321369Sdim Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 232344779Sdim 233344779Sdim auto RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags); 234344779Sdim assert(RefKind != AArch64MCExpr::VK_INVALID && 235344779Sdim "Invalid relocation requested"); 236341825Sdim Expr = AArch64MCExpr::create(Expr, RefKind, Ctx); 237344779Sdim 238321369Sdim return MCOperand::createExpr(Expr); 239321369Sdim} 240321369Sdim 241276479SdimMCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO, 242276479Sdim MCSymbol *Sym) const { 243314564Sdim if (Printer.TM.getTargetTriple().isOSDarwin()) 244276479Sdim return lowerSymbolOperandDarwin(MO, Sym); 245321369Sdim if (Printer.TM.getTargetTriple().isOSBinFormatCOFF()) 246321369Sdim return lowerSymbolOperandCOFF(MO, Sym); 247276479Sdim 248321369Sdim assert(Printer.TM.getTargetTriple().isOSBinFormatELF() && "Invalid target"); 249276479Sdim return lowerSymbolOperandELF(MO, Sym); 250276479Sdim} 251276479Sdim 252276479Sdimbool AArch64MCInstLower::lowerOperand(const MachineOperand &MO, 253276479Sdim MCOperand &MCOp) const { 254249259Sdim switch (MO.getType()) { 255276479Sdim default: 256276479Sdim llvm_unreachable("unknown operand type"); 257249259Sdim case MachineOperand::MO_Register: 258276479Sdim // Ignore all implicit register operands. 259249259Sdim if (MO.isImplicit()) 260249259Sdim return false; 261288943Sdim MCOp = MCOperand::createReg(MO.getReg()); 262249259Sdim break; 263276479Sdim case MachineOperand::MO_RegisterMask: 264276479Sdim // Regmasks are like implicit defs. 265276479Sdim return false; 266249259Sdim case MachineOperand::MO_Immediate: 267288943Sdim MCOp = MCOperand::createImm(MO.getImm()); 268249259Sdim break; 269276479Sdim case MachineOperand::MO_MachineBasicBlock: 270288943Sdim MCOp = MCOperand::createExpr( 271288943Sdim MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx)); 272261991Sdim break; 273276479Sdim case MachineOperand::MO_GlobalAddress: 274276479Sdim MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); 275249259Sdim break; 276249259Sdim case MachineOperand::MO_ExternalSymbol: 277276479Sdim MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); 278249259Sdim break; 279288943Sdim case MachineOperand::MO_MCSymbol: 280288943Sdim MCOp = LowerSymbolOperand(MO, MO.getMCSymbol()); 281288943Sdim break; 282249259Sdim case MachineOperand::MO_JumpTableIndex: 283276479Sdim MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex())); 284249259Sdim break; 285249259Sdim case MachineOperand::MO_ConstantPoolIndex: 286276479Sdim MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex())); 287249259Sdim break; 288276479Sdim case MachineOperand::MO_BlockAddress: 289276479Sdim MCOp = LowerSymbolOperand( 290276479Sdim MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress())); 291276479Sdim break; 292249259Sdim } 293249259Sdim return true; 294249259Sdim} 295249259Sdim 296276479Sdimvoid AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 297249259Sdim OutMI.setOpcode(MI->getOpcode()); 298249259Sdim 299296417Sdim for (const MachineOperand &MO : MI->operands()) { 300249259Sdim MCOperand MCOp; 301296417Sdim if (lowerOperand(MO, MCOp)) 302249259Sdim OutMI.addOperand(MCOp); 303249259Sdim } 304344779Sdim 305344779Sdim switch (OutMI.getOpcode()) { 306344779Sdim case AArch64::CATCHRET: 307344779Sdim OutMI = MCInst(); 308344779Sdim OutMI.setOpcode(AArch64::RET); 309344779Sdim OutMI.addOperand(MCOperand::createReg(AArch64::LR)); 310344779Sdim break; 311344779Sdim case AArch64::CLEANUPRET: 312344779Sdim OutMI = MCInst(); 313344779Sdim OutMI.setOpcode(AArch64::RET); 314344779Sdim OutMI.addOperand(MCOperand::createReg(AArch64::LR)); 315344779Sdim break; 316344779Sdim } 317249259Sdim} 318