10b57cec5SDimitry Andric //==-- AArch64MCInstLower.cpp - Convert AArch64 MachineInstr to an MCInst --==// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains code to lower AArch64 MachineInstrs to their corresponding 100b57cec5SDimitry Andric // MCInst records. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "AArch64MCInstLower.h" 150b57cec5SDimitry Andric #include "MCTargetDesc/AArch64MCExpr.h" 160b57cec5SDimitry Andric #include "Utils/AArch64BaseInfo.h" 170b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 180b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstr.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h" 210b57cec5SDimitry Andric #include "llvm/IR/Mangler.h" 220b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 230b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 240b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 25bdd1243dSDimitry Andric #include "llvm/MC/MCStreamer.h" 26*439352acSDimitry Andric #include "llvm/Object/COFF.h" 270b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h" 280b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 290b57cec5SDimitry Andric #include "llvm/Target/TargetLoweringObjectFile.h" 300b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 310b57cec5SDimitry Andric using namespace llvm; 32*439352acSDimitry Andric using namespace llvm::object; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric extern cl::opt<bool> EnableAArch64ELFLocalDynamicTLSGeneration; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer) 370b57cec5SDimitry Andric : Ctx(ctx), Printer(printer) {} 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric MCSymbol * 400b57cec5SDimitry Andric AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const { 417a6dacacSDimitry Andric return GetGlobalValueSymbol(MO.getGlobal(), MO.getTargetFlags()); 427a6dacacSDimitry Andric } 437a6dacacSDimitry Andric 447a6dacacSDimitry Andric MCSymbol *AArch64MCInstLower::GetGlobalValueSymbol(const GlobalValue *GV, 457a6dacacSDimitry Andric unsigned TargetFlags) const { 460b57cec5SDimitry Andric const Triple &TheTriple = Printer.TM.getTargetTriple(); 470b57cec5SDimitry Andric if (!TheTriple.isOSBinFormatCOFF()) 48fe6060f1SDimitry Andric return Printer.getSymbolPreferLocal(*GV); 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric assert(TheTriple.isOSWindows() && 510b57cec5SDimitry Andric "Windows is the only supported COFF target"); 520b57cec5SDimitry Andric 53bdd1243dSDimitry Andric bool IsIndirect = 547a6dacacSDimitry Andric (TargetFlags & (AArch64II::MO_DLLIMPORT | AArch64II::MO_COFFSTUB)); 557a6dacacSDimitry Andric if (!IsIndirect) { 567a6dacacSDimitry Andric // For ARM64EC, symbol lookup in the MSVC linker has limited awareness 577a6dacacSDimitry Andric // of ARM64EC mangling ("#"/"$$h"). So object files need to refer to both 587a6dacacSDimitry Andric // the mangled and unmangled names of ARM64EC symbols, even if they aren't 597a6dacacSDimitry Andric // actually used by any relocations. Emit the necessary references here. 607a6dacacSDimitry Andric if (!TheTriple.isWindowsArm64EC() || !isa<Function>(GV) || 617a6dacacSDimitry Andric !GV->hasExternalLinkage()) 620b57cec5SDimitry Andric return Printer.getSymbol(GV); 630b57cec5SDimitry Andric 647a6dacacSDimitry Andric StringRef Name = Printer.getSymbol(GV)->getName(); 657a6dacacSDimitry Andric // Don't mangle ARM64EC runtime functions. 667a6dacacSDimitry Andric static constexpr StringLiteral ExcludedFns[] = { 677a6dacacSDimitry Andric "__os_arm64x_check_icall_cfg", "__os_arm64x_dispatch_call_no_redirect", 687a6dacacSDimitry Andric "__os_arm64x_check_icall"}; 697a6dacacSDimitry Andric if (is_contained(ExcludedFns, Name)) 707a6dacacSDimitry Andric return Printer.getSymbol(GV); 717a6dacacSDimitry Andric 727a6dacacSDimitry Andric if (std::optional<std::string> MangledName = 737a6dacacSDimitry Andric getArm64ECMangledFunctionName(Name.str())) { 747a6dacacSDimitry Andric MCSymbol *MangledSym = Ctx.getOrCreateSymbol(MangledName.value()); 757a6dacacSDimitry Andric if (!cast<Function>(GV)->hasMetadata("arm64ec_hasguestexit")) { 767a6dacacSDimitry Andric Printer.OutStreamer->emitSymbolAttribute(Printer.getSymbol(GV), 777a6dacacSDimitry Andric MCSA_WeakAntiDep); 787a6dacacSDimitry Andric Printer.OutStreamer->emitAssignment( 797a6dacacSDimitry Andric Printer.getSymbol(GV), 807a6dacacSDimitry Andric MCSymbolRefExpr::create(MangledSym, MCSymbolRefExpr::VK_WEAKREF, 817a6dacacSDimitry Andric Ctx)); 827a6dacacSDimitry Andric Printer.OutStreamer->emitSymbolAttribute(MangledSym, MCSA_WeakAntiDep); 837a6dacacSDimitry Andric Printer.OutStreamer->emitAssignment( 847a6dacacSDimitry Andric MangledSym, 857a6dacacSDimitry Andric MCSymbolRefExpr::create(Printer.getSymbol(GV), 867a6dacacSDimitry Andric MCSymbolRefExpr::VK_WEAKREF, Ctx)); 877a6dacacSDimitry Andric } 887a6dacacSDimitry Andric 897a6dacacSDimitry Andric if (TargetFlags & AArch64II::MO_ARM64EC_CALLMANGLE) 907a6dacacSDimitry Andric return MangledSym; 917a6dacacSDimitry Andric } 927a6dacacSDimitry Andric 937a6dacacSDimitry Andric return Printer.getSymbol(GV); 947a6dacacSDimitry Andric } 957a6dacacSDimitry Andric 960b57cec5SDimitry Andric SmallString<128> Name; 97bdd1243dSDimitry Andric 987a6dacacSDimitry Andric if ((TargetFlags & AArch64II::MO_DLLIMPORT) && 997a6dacacSDimitry Andric TheTriple.isWindowsArm64EC() && 1007a6dacacSDimitry Andric !(TargetFlags & AArch64II::MO_ARM64EC_CALLMANGLE) && 1017a6dacacSDimitry Andric isa<Function>(GV)) { 102bdd1243dSDimitry Andric // __imp_aux is specific to arm64EC; it represents the actual address of 103bdd1243dSDimitry Andric // an imported function without any thunks. 104bdd1243dSDimitry Andric // 105bdd1243dSDimitry Andric // If we see a reference to an "aux" symbol, also emit a reference to the 106bdd1243dSDimitry Andric // corresponding non-aux symbol. Otherwise, the Microsoft linker behaves 107bdd1243dSDimitry Andric // strangely when linking against x64 import libararies. 108bdd1243dSDimitry Andric // 109bdd1243dSDimitry Andric // emitSymbolAttribute() doesn't have any real effect here; it just 110bdd1243dSDimitry Andric // ensures the symbol name appears in the assembly without any 111bdd1243dSDimitry Andric // side-effects. It might make sense to design a cleaner way to express 112bdd1243dSDimitry Andric // this. 1130b57cec5SDimitry Andric Name = "__imp_"; 114bdd1243dSDimitry Andric Printer.TM.getNameWithPrefix(Name, GV, 115bdd1243dSDimitry Andric Printer.getObjFileLowering().getMangler()); 116bdd1243dSDimitry Andric MCSymbol *ExtraSym = Ctx.getOrCreateSymbol(Name); 117bdd1243dSDimitry Andric Printer.OutStreamer->emitSymbolAttribute(ExtraSym, MCSA_Global); 118bdd1243dSDimitry Andric 119bdd1243dSDimitry Andric Name = "__imp_aux_"; 120bdd1243dSDimitry Andric } else if (TargetFlags & AArch64II::MO_DLLIMPORT) { 121bdd1243dSDimitry Andric Name = "__imp_"; 122bdd1243dSDimitry Andric } else if (TargetFlags & AArch64II::MO_COFFSTUB) { 1230b57cec5SDimitry Andric Name = ".refptr."; 124bdd1243dSDimitry Andric } 1250b57cec5SDimitry Andric Printer.TM.getNameWithPrefix(Name, GV, 1260b57cec5SDimitry Andric Printer.getObjFileLowering().getMangler()); 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric MCSymbol *MCSym = Ctx.getOrCreateSymbol(Name); 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric if (TargetFlags & AArch64II::MO_COFFSTUB) { 1310b57cec5SDimitry Andric MachineModuleInfoCOFF &MMICOFF = 1320b57cec5SDimitry Andric Printer.MMI->getObjFileInfo<MachineModuleInfoCOFF>(); 1330b57cec5SDimitry Andric MachineModuleInfoImpl::StubValueTy &StubSym = 1340b57cec5SDimitry Andric MMICOFF.getGVStubEntry(MCSym); 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric if (!StubSym.getPointer()) 1370b57cec5SDimitry Andric StubSym = MachineModuleInfoImpl::StubValueTy(Printer.getSymbol(GV), true); 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric return MCSym; 1410b57cec5SDimitry Andric } 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric MCSymbol * 1440b57cec5SDimitry Andric AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const { 1450b57cec5SDimitry Andric return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 1485f757f3fSDimitry Andric MCOperand AArch64MCInstLower::lowerSymbolOperandMachO(const MachineOperand &MO, 1490b57cec5SDimitry Andric MCSymbol *Sym) const { 1500b57cec5SDimitry Andric // FIXME: We would like an efficient form for this, so we don't have to do a 1510b57cec5SDimitry Andric // lot of extra uniquing. 1520b57cec5SDimitry Andric MCSymbolRefExpr::VariantKind RefKind = MCSymbolRefExpr::VK_None; 1530b57cec5SDimitry Andric if ((MO.getTargetFlags() & AArch64II::MO_GOT) != 0) { 1540b57cec5SDimitry Andric if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 1550b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_GOTPAGE; 1560b57cec5SDimitry Andric else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 1570b57cec5SDimitry Andric AArch64II::MO_PAGEOFF) 1580b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_GOTPAGEOFF; 1590b57cec5SDimitry Andric else 1600b57cec5SDimitry Andric llvm_unreachable("Unexpected target flags with MO_GOT on GV operand"); 1610b57cec5SDimitry Andric } else if ((MO.getTargetFlags() & AArch64II::MO_TLS) != 0) { 1620b57cec5SDimitry Andric if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 1630b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_TLVPPAGE; 1640b57cec5SDimitry Andric else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 1650b57cec5SDimitry Andric AArch64II::MO_PAGEOFF) 1660b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_TLVPPAGEOFF; 1670b57cec5SDimitry Andric else 1680b57cec5SDimitry Andric llvm_unreachable("Unexpected target flags with MO_TLS on GV operand"); 1690b57cec5SDimitry Andric } else { 1700b57cec5SDimitry Andric if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 1710b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PAGE; 1720b57cec5SDimitry Andric else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 1730b57cec5SDimitry Andric AArch64II::MO_PAGEOFF) 1740b57cec5SDimitry Andric RefKind = MCSymbolRefExpr::VK_PAGEOFF; 1750b57cec5SDimitry Andric } 1760b57cec5SDimitry Andric const MCExpr *Expr = MCSymbolRefExpr::create(Sym, RefKind, Ctx); 1770b57cec5SDimitry Andric if (!MO.isJTI() && MO.getOffset()) 1780b57cec5SDimitry Andric Expr = MCBinaryExpr::createAdd( 1790b57cec5SDimitry Andric Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 1800b57cec5SDimitry Andric return MCOperand::createExpr(Expr); 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric MCOperand AArch64MCInstLower::lowerSymbolOperandELF(const MachineOperand &MO, 1840b57cec5SDimitry Andric MCSymbol *Sym) const { 1850b57cec5SDimitry Andric uint32_t RefFlags = 0; 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric if (MO.getTargetFlags() & AArch64II::MO_GOT) 1880b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_GOT; 1890b57cec5SDimitry Andric else if (MO.getTargetFlags() & AArch64II::MO_TLS) { 1900b57cec5SDimitry Andric TLSModel::Model Model; 1910b57cec5SDimitry Andric if (MO.isGlobal()) { 1920b57cec5SDimitry Andric const GlobalValue *GV = MO.getGlobal(); 1930b57cec5SDimitry Andric Model = Printer.TM.getTLSModel(GV); 1940b57cec5SDimitry Andric if (!EnableAArch64ELFLocalDynamicTLSGeneration && 1950b57cec5SDimitry Andric Model == TLSModel::LocalDynamic) 1960b57cec5SDimitry Andric Model = TLSModel::GeneralDynamic; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric } else { 1990b57cec5SDimitry Andric assert(MO.isSymbol() && 2000b57cec5SDimitry Andric StringRef(MO.getSymbolName()) == "_TLS_MODULE_BASE_" && 2010b57cec5SDimitry Andric "unexpected external TLS symbol"); 2020b57cec5SDimitry Andric // The general dynamic access sequence is used to get the 2030b57cec5SDimitry Andric // address of _TLS_MODULE_BASE_. 2040b57cec5SDimitry Andric Model = TLSModel::GeneralDynamic; 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric switch (Model) { 2070b57cec5SDimitry Andric case TLSModel::InitialExec: 2080b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_GOTTPREL; 2090b57cec5SDimitry Andric break; 2100b57cec5SDimitry Andric case TLSModel::LocalExec: 2110b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_TPREL; 2120b57cec5SDimitry Andric break; 2130b57cec5SDimitry Andric case TLSModel::LocalDynamic: 2140b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_DTPREL; 2150b57cec5SDimitry Andric break; 2160b57cec5SDimitry Andric case TLSModel::GeneralDynamic: 2170b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_TLSDESC; 2180b57cec5SDimitry Andric break; 2190b57cec5SDimitry Andric } 2208bcb0991SDimitry Andric } else if (MO.getTargetFlags() & AArch64II::MO_PREL) { 2218bcb0991SDimitry Andric RefFlags |= AArch64MCExpr::VK_PREL; 2220b57cec5SDimitry Andric } else { 2230b57cec5SDimitry Andric // No modifier means this is a generic reference, classified as absolute for 2240b57cec5SDimitry Andric // the cases where it matters (:abs_g0: etc). 2250b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_ABS; 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 2290b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_PAGE; 2300b57cec5SDimitry Andric else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 2310b57cec5SDimitry Andric AArch64II::MO_PAGEOFF) 2320b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_PAGEOFF; 2330b57cec5SDimitry Andric else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3) 2340b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_G3; 2350b57cec5SDimitry Andric else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2) 2360b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_G2; 2370b57cec5SDimitry Andric else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1) 2380b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_G1; 2390b57cec5SDimitry Andric else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0) 2400b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_G0; 2410b57cec5SDimitry Andric else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_HI12) 2420b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_HI12; 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric if (MO.getTargetFlags() & AArch64II::MO_NC) 2450b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_NC; 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric const MCExpr *Expr = 2480b57cec5SDimitry Andric MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); 2490b57cec5SDimitry Andric if (!MO.isJTI() && MO.getOffset()) 2500b57cec5SDimitry Andric Expr = MCBinaryExpr::createAdd( 2510b57cec5SDimitry Andric Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric AArch64MCExpr::VariantKind RefKind; 2540b57cec5SDimitry Andric RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags); 2550b57cec5SDimitry Andric Expr = AArch64MCExpr::create(Expr, RefKind, Ctx); 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric return MCOperand::createExpr(Expr); 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric 2600b57cec5SDimitry Andric MCOperand AArch64MCInstLower::lowerSymbolOperandCOFF(const MachineOperand &MO, 2610b57cec5SDimitry Andric MCSymbol *Sym) const { 2620b57cec5SDimitry Andric uint32_t RefFlags = 0; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric if (MO.getTargetFlags() & AArch64II::MO_TLS) { 2650b57cec5SDimitry Andric if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGEOFF) 2660b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_SECREL_LO12; 2670b57cec5SDimitry Andric else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 2680b57cec5SDimitry Andric AArch64II::MO_HI12) 2690b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_SECREL_HI12; 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric } else if (MO.getTargetFlags() & AArch64II::MO_S) { 2720b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_SABS; 2730b57cec5SDimitry Andric } else { 2740b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_ABS; 275e8d8bef9SDimitry Andric 276e8d8bef9SDimitry Andric if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_PAGE) 277e8d8bef9SDimitry Andric RefFlags |= AArch64MCExpr::VK_PAGE; 278e8d8bef9SDimitry Andric else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == 279e8d8bef9SDimitry Andric AArch64II::MO_PAGEOFF) 280e8d8bef9SDimitry Andric RefFlags |= AArch64MCExpr::VK_PAGEOFF | AArch64MCExpr::VK_NC; 2810b57cec5SDimitry Andric } 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G3) 2840b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_G3; 2850b57cec5SDimitry Andric else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G2) 2860b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_G2; 2870b57cec5SDimitry Andric else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G1) 2880b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_G1; 2890b57cec5SDimitry Andric else if ((MO.getTargetFlags() & AArch64II::MO_FRAGMENT) == AArch64II::MO_G0) 2900b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_G0; 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric // FIXME: Currently we only set VK_NC for MO_G3/MO_G2/MO_G1/MO_G0. This is 2930b57cec5SDimitry Andric // because setting VK_NC for others would mean setting their respective 2940b57cec5SDimitry Andric // RefFlags correctly. We should do this in a separate patch. 2950b57cec5SDimitry Andric if (MO.getTargetFlags() & AArch64II::MO_NC) { 2960b57cec5SDimitry Andric auto MOFrag = (MO.getTargetFlags() & AArch64II::MO_FRAGMENT); 2970b57cec5SDimitry Andric if (MOFrag == AArch64II::MO_G3 || MOFrag == AArch64II::MO_G2 || 2980b57cec5SDimitry Andric MOFrag == AArch64II::MO_G1 || MOFrag == AArch64II::MO_G0) 2990b57cec5SDimitry Andric RefFlags |= AArch64MCExpr::VK_NC; 3000b57cec5SDimitry Andric } 3010b57cec5SDimitry Andric 3020b57cec5SDimitry Andric const MCExpr *Expr = 3030b57cec5SDimitry Andric MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); 3040b57cec5SDimitry Andric if (!MO.isJTI() && MO.getOffset()) 3050b57cec5SDimitry Andric Expr = MCBinaryExpr::createAdd( 3060b57cec5SDimitry Andric Expr, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 3070b57cec5SDimitry Andric 3080b57cec5SDimitry Andric auto RefKind = static_cast<AArch64MCExpr::VariantKind>(RefFlags); 3090b57cec5SDimitry Andric assert(RefKind != AArch64MCExpr::VK_INVALID && 3100b57cec5SDimitry Andric "Invalid relocation requested"); 3110b57cec5SDimitry Andric Expr = AArch64MCExpr::create(Expr, RefKind, Ctx); 3120b57cec5SDimitry Andric 3130b57cec5SDimitry Andric return MCOperand::createExpr(Expr); 3140b57cec5SDimitry Andric } 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric MCOperand AArch64MCInstLower::LowerSymbolOperand(const MachineOperand &MO, 3170b57cec5SDimitry Andric MCSymbol *Sym) const { 3185f757f3fSDimitry Andric if (Printer.TM.getTargetTriple().isOSBinFormatMachO()) 3195f757f3fSDimitry Andric return lowerSymbolOperandMachO(MO, Sym); 3200b57cec5SDimitry Andric if (Printer.TM.getTargetTriple().isOSBinFormatCOFF()) 3210b57cec5SDimitry Andric return lowerSymbolOperandCOFF(MO, Sym); 3220b57cec5SDimitry Andric 3230b57cec5SDimitry Andric assert(Printer.TM.getTargetTriple().isOSBinFormatELF() && "Invalid target"); 3240b57cec5SDimitry Andric return lowerSymbolOperandELF(MO, Sym); 3250b57cec5SDimitry Andric } 3260b57cec5SDimitry Andric 3270b57cec5SDimitry Andric bool AArch64MCInstLower::lowerOperand(const MachineOperand &MO, 3280b57cec5SDimitry Andric MCOperand &MCOp) const { 3290b57cec5SDimitry Andric switch (MO.getType()) { 3300b57cec5SDimitry Andric default: 3310b57cec5SDimitry Andric llvm_unreachable("unknown operand type"); 3320b57cec5SDimitry Andric case MachineOperand::MO_Register: 3330b57cec5SDimitry Andric // Ignore all implicit register operands. 3340b57cec5SDimitry Andric if (MO.isImplicit()) 3350b57cec5SDimitry Andric return false; 3360b57cec5SDimitry Andric MCOp = MCOperand::createReg(MO.getReg()); 3370b57cec5SDimitry Andric break; 3380b57cec5SDimitry Andric case MachineOperand::MO_RegisterMask: 3390b57cec5SDimitry Andric // Regmasks are like implicit defs. 3400b57cec5SDimitry Andric return false; 3410b57cec5SDimitry Andric case MachineOperand::MO_Immediate: 3420b57cec5SDimitry Andric MCOp = MCOperand::createImm(MO.getImm()); 3430b57cec5SDimitry Andric break; 3440b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 3450b57cec5SDimitry Andric MCOp = MCOperand::createExpr( 3460b57cec5SDimitry Andric MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx)); 3470b57cec5SDimitry Andric break; 3480b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: 3490b57cec5SDimitry Andric MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); 3500b57cec5SDimitry Andric break; 3510b57cec5SDimitry Andric case MachineOperand::MO_ExternalSymbol: 3520b57cec5SDimitry Andric MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); 3530b57cec5SDimitry Andric break; 3540b57cec5SDimitry Andric case MachineOperand::MO_MCSymbol: 3550b57cec5SDimitry Andric MCOp = LowerSymbolOperand(MO, MO.getMCSymbol()); 3560b57cec5SDimitry Andric break; 3570b57cec5SDimitry Andric case MachineOperand::MO_JumpTableIndex: 3580b57cec5SDimitry Andric MCOp = LowerSymbolOperand(MO, Printer.GetJTISymbol(MO.getIndex())); 3590b57cec5SDimitry Andric break; 3600b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 3610b57cec5SDimitry Andric MCOp = LowerSymbolOperand(MO, Printer.GetCPISymbol(MO.getIndex())); 3620b57cec5SDimitry Andric break; 3630b57cec5SDimitry Andric case MachineOperand::MO_BlockAddress: 3640b57cec5SDimitry Andric MCOp = LowerSymbolOperand( 3650b57cec5SDimitry Andric MO, Printer.GetBlockAddressSymbol(MO.getBlockAddress())); 3660b57cec5SDimitry Andric break; 3670b57cec5SDimitry Andric } 3680b57cec5SDimitry Andric return true; 3690b57cec5SDimitry Andric } 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric void AArch64MCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { 3720b57cec5SDimitry Andric OutMI.setOpcode(MI->getOpcode()); 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric for (const MachineOperand &MO : MI->operands()) { 3750b57cec5SDimitry Andric MCOperand MCOp; 3760b57cec5SDimitry Andric if (lowerOperand(MO, MCOp)) 3770b57cec5SDimitry Andric OutMI.addOperand(MCOp); 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric 3800b57cec5SDimitry Andric switch (OutMI.getOpcode()) { 3810b57cec5SDimitry Andric case AArch64::CATCHRET: 3820b57cec5SDimitry Andric OutMI = MCInst(); 3830b57cec5SDimitry Andric OutMI.setOpcode(AArch64::RET); 3840b57cec5SDimitry Andric OutMI.addOperand(MCOperand::createReg(AArch64::LR)); 3850b57cec5SDimitry Andric break; 3860b57cec5SDimitry Andric case AArch64::CLEANUPRET: 3870b57cec5SDimitry Andric OutMI = MCInst(); 3880b57cec5SDimitry Andric OutMI.setOpcode(AArch64::RET); 3890b57cec5SDimitry Andric OutMI.addOperand(MCOperand::createReg(AArch64::LR)); 3900b57cec5SDimitry Andric break; 3910b57cec5SDimitry Andric } 3920b57cec5SDimitry Andric } 393