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