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