xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64MCInstLower.cpp (revision 439352ac8257c8419cb4a662abb7f260f31f9932)
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