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
AArch64MCInstLower(MCContext & ctx,AsmPrinter & printer)370b57cec5SDimitry Andric AArch64MCInstLower::AArch64MCInstLower(MCContext &ctx, AsmPrinter &printer)
380b57cec5SDimitry Andric : Ctx(ctx), Printer(printer) {}
390b57cec5SDimitry Andric
400b57cec5SDimitry Andric MCSymbol *
GetGlobalAddressSymbol(const MachineOperand & MO) const410b57cec5SDimitry Andric AArch64MCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
427a6dacacSDimitry Andric return GetGlobalValueSymbol(MO.getGlobal(), MO.getTargetFlags());
437a6dacacSDimitry Andric }
447a6dacacSDimitry Andric
GetGlobalValueSymbol(const GlobalValue * GV,unsigned TargetFlags) const457a6dacacSDimitry 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 *
GetExternalSymbolSymbol(const MachineOperand & MO) const1450b57cec5SDimitry Andric AArch64MCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const {
1460b57cec5SDimitry Andric return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric
lowerSymbolOperandMachO(const MachineOperand & MO,MCSymbol * Sym) const1495f757f3fSDimitry 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
lowerSymbolOperandELF(const MachineOperand & MO,MCSymbol * Sym) const1840b57cec5SDimitry 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
lowerSymbolOperandCOFF(const MachineOperand & MO,MCSymbol * Sym) const2610b57cec5SDimitry 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
LowerSymbolOperand(const MachineOperand & MO,MCSymbol * Sym) const3170b57cec5SDimitry 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
lowerOperand(const MachineOperand & MO,MCOperand & MCOp) const3280b57cec5SDimitry 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
Lower(const MachineInstr * MI,MCInst & OutMI) const3720b57cec5SDimitry 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