AArch64AsmPrinter.cpp 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473
  1. //===- AArch64AsmPrinter.cpp - AArch64 LLVM assembly writer ---------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file contains a printer that converts from our internal representation
  10. // of machine-dependent LLVM code to the AArch64 assembly language.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "AArch64.h"
  14. #include "AArch64MCInstLower.h"
  15. #include "AArch64MachineFunctionInfo.h"
  16. #include "AArch64RegisterInfo.h"
  17. #include "AArch64Subtarget.h"
  18. #include "AArch64TargetObjectFile.h"
  19. #include "MCTargetDesc/AArch64AddressingModes.h"
  20. #include "MCTargetDesc/AArch64InstPrinter.h"
  21. #include "MCTargetDesc/AArch64MCExpr.h"
  22. #include "MCTargetDesc/AArch64MCTargetDesc.h"
  23. #include "MCTargetDesc/AArch64TargetStreamer.h"
  24. #include "TargetInfo/AArch64TargetInfo.h"
  25. #include "Utils/AArch64BaseInfo.h"
  26. #include "llvm/ADT/SmallString.h"
  27. #include "llvm/ADT/SmallVector.h"
  28. #include "llvm/ADT/StringRef.h"
  29. #include "llvm/ADT/Triple.h"
  30. #include "llvm/ADT/Twine.h"
  31. #include "llvm/BinaryFormat/COFF.h"
  32. #include "llvm/BinaryFormat/ELF.h"
  33. #include "llvm/CodeGen/AsmPrinter.h"
  34. #include "llvm/CodeGen/FaultMaps.h"
  35. #include "llvm/CodeGen/MachineBasicBlock.h"
  36. #include "llvm/CodeGen/MachineFunction.h"
  37. #include "llvm/CodeGen/MachineInstr.h"
  38. #include "llvm/CodeGen/MachineJumpTableInfo.h"
  39. #include "llvm/CodeGen/MachineModuleInfoImpls.h"
  40. #include "llvm/CodeGen/MachineOperand.h"
  41. #include "llvm/CodeGen/StackMaps.h"
  42. #include "llvm/CodeGen/TargetRegisterInfo.h"
  43. #include "llvm/IR/DataLayout.h"
  44. #include "llvm/IR/DebugInfoMetadata.h"
  45. #include "llvm/MC/MCAsmInfo.h"
  46. #include "llvm/MC/MCContext.h"
  47. #include "llvm/MC/MCInst.h"
  48. #include "llvm/MC/MCInstBuilder.h"
  49. #include "llvm/MC/MCSectionELF.h"
  50. #include "llvm/MC/MCStreamer.h"
  51. #include "llvm/MC/MCSymbol.h"
  52. #include "llvm/Support/Casting.h"
  53. #include "llvm/Support/ErrorHandling.h"
  54. #include "llvm/Support/TargetRegistry.h"
  55. #include "llvm/Support/raw_ostream.h"
  56. #include "llvm/Target/TargetMachine.h"
  57. #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
  58. #include <algorithm>
  59. #include <cassert>
  60. #include <cstdint>
  61. #include <map>
  62. #include <memory>
  63. using namespace llvm;
  64. #define DEBUG_TYPE "asm-printer"
  65. namespace {
  66. class AArch64AsmPrinter : public AsmPrinter {
  67. AArch64MCInstLower MCInstLowering;
  68. StackMaps SM;
  69. FaultMaps FM;
  70. const AArch64Subtarget *STI;
  71. public:
  72. AArch64AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer)
  73. : AsmPrinter(TM, std::move(Streamer)), MCInstLowering(OutContext, *this),
  74. SM(*this), FM(*this) {}
  75. StringRef getPassName() const override { return "AArch64 Assembly Printer"; }
  76. /// Wrapper for MCInstLowering.lowerOperand() for the
  77. /// tblgen'erated pseudo lowering.
  78. bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
  79. return MCInstLowering.lowerOperand(MO, MCOp);
  80. }
  81. void emitStartOfAsmFile(Module &M) override;
  82. void emitJumpTableInfo() override;
  83. void emitFunctionEntryLabel() override;
  84. void LowerJumpTableDest(MCStreamer &OutStreamer, const MachineInstr &MI);
  85. void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
  86. const MachineInstr &MI);
  87. void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
  88. const MachineInstr &MI);
  89. void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
  90. const MachineInstr &MI);
  91. void LowerFAULTING_OP(const MachineInstr &MI);
  92. void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
  93. void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
  94. void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
  95. typedef std::tuple<unsigned, bool, uint32_t> HwasanMemaccessTuple;
  96. std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
  97. void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);
  98. void EmitHwasanMemaccessSymbols(Module &M);
  99. void EmitSled(const MachineInstr &MI, SledKind Kind);
  100. /// tblgen'erated driver function for lowering simple MI->MC
  101. /// pseudo instructions.
  102. bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
  103. const MachineInstr *MI);
  104. void emitInstruction(const MachineInstr *MI) override;
  105. void emitFunctionHeaderComment() override;
  106. void getAnalysisUsage(AnalysisUsage &AU) const override {
  107. AsmPrinter::getAnalysisUsage(AU);
  108. AU.setPreservesAll();
  109. }
  110. bool runOnMachineFunction(MachineFunction &MF) override {
  111. AArch64FI = MF.getInfo<AArch64FunctionInfo>();
  112. STI = static_cast<const AArch64Subtarget*>(&MF.getSubtarget());
  113. SetupMachineFunction(MF);
  114. if (STI->isTargetCOFF()) {
  115. bool Internal = MF.getFunction().hasInternalLinkage();
  116. COFF::SymbolStorageClass Scl = Internal ? COFF::IMAGE_SYM_CLASS_STATIC
  117. : COFF::IMAGE_SYM_CLASS_EXTERNAL;
  118. int Type =
  119. COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT;
  120. OutStreamer->BeginCOFFSymbolDef(CurrentFnSym);
  121. OutStreamer->EmitCOFFSymbolStorageClass(Scl);
  122. OutStreamer->EmitCOFFSymbolType(Type);
  123. OutStreamer->EndCOFFSymbolDef();
  124. }
  125. // Emit the rest of the function body.
  126. emitFunctionBody();
  127. // Emit the XRay table for this function.
  128. emitXRayTable();
  129. // We didn't modify anything.
  130. return false;
  131. }
  132. private:
  133. void printOperand(const MachineInstr *MI, unsigned OpNum, raw_ostream &O);
  134. bool printAsmMRegister(const MachineOperand &MO, char Mode, raw_ostream &O);
  135. bool printAsmRegInClass(const MachineOperand &MO,
  136. const TargetRegisterClass *RC, unsigned AltName,
  137. raw_ostream &O);
  138. bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
  139. const char *ExtraCode, raw_ostream &O) override;
  140. bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
  141. const char *ExtraCode, raw_ostream &O) override;
  142. void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
  143. void emitFunctionBodyEnd() override;
  144. MCSymbol *GetCPISymbol(unsigned CPID) const override;
  145. void emitEndOfAsmFile(Module &M) override;
  146. AArch64FunctionInfo *AArch64FI = nullptr;
  147. /// Emit the LOHs contained in AArch64FI.
  148. void EmitLOHs();
  149. /// Emit instruction to set float register to zero.
  150. void EmitFMov0(const MachineInstr &MI);
  151. using MInstToMCSymbol = std::map<const MachineInstr *, MCSymbol *>;
  152. MInstToMCSymbol LOHInstToLabel;
  153. };
  154. } // end anonymous namespace
  155. void AArch64AsmPrinter::emitStartOfAsmFile(Module &M) {
  156. if (!TM.getTargetTriple().isOSBinFormatELF())
  157. return;
  158. // Assemble feature flags that may require creation of a note section.
  159. unsigned Flags = 0;
  160. if (const auto *BTE = mdconst::extract_or_null<ConstantInt>(
  161. M.getModuleFlag("branch-target-enforcement")))
  162. if (BTE->getZExtValue())
  163. Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
  164. if (const auto *Sign = mdconst::extract_or_null<ConstantInt>(
  165. M.getModuleFlag("sign-return-address")))
  166. if (Sign->getZExtValue())
  167. Flags |= ELF::GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
  168. if (Flags == 0)
  169. return;
  170. // Emit a .note.gnu.property section with the flags.
  171. if (auto *TS = static_cast<AArch64TargetStreamer *>(
  172. OutStreamer->getTargetStreamer()))
  173. TS->emitNoteSection(Flags);
  174. }
  175. void AArch64AsmPrinter::emitFunctionHeaderComment() {
  176. const AArch64FunctionInfo *FI = MF->getInfo<AArch64FunctionInfo>();
  177. Optional<std::string> OutlinerString = FI->getOutliningStyle();
  178. if (OutlinerString != None)
  179. OutStreamer->GetCommentOS() << ' ' << OutlinerString;
  180. }
  181. void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI)
  182. {
  183. const Function &F = MF->getFunction();
  184. if (F.hasFnAttribute("patchable-function-entry")) {
  185. unsigned Num;
  186. if (F.getFnAttribute("patchable-function-entry")
  187. .getValueAsString()
  188. .getAsInteger(10, Num))
  189. return;
  190. emitNops(Num);
  191. return;
  192. }
  193. EmitSled(MI, SledKind::FUNCTION_ENTER);
  194. }
  195. void AArch64AsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI)
  196. {
  197. EmitSled(MI, SledKind::FUNCTION_EXIT);
  198. }
  199. void AArch64AsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)
  200. {
  201. EmitSled(MI, SledKind::TAIL_CALL);
  202. }
  203. void AArch64AsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind)
  204. {
  205. static const int8_t NoopsInSledCount = 7;
  206. // We want to emit the following pattern:
  207. //
  208. // .Lxray_sled_N:
  209. // ALIGN
  210. // B #32
  211. // ; 7 NOP instructions (28 bytes)
  212. // .tmpN
  213. //
  214. // We need the 28 bytes (7 instructions) because at runtime, we'd be patching
  215. // over the full 32 bytes (8 instructions) with the following pattern:
  216. //
  217. // STP X0, X30, [SP, #-16]! ; push X0 and the link register to the stack
  218. // LDR W0, #12 ; W0 := function ID
  219. // LDR X16,#12 ; X16 := addr of __xray_FunctionEntry or __xray_FunctionExit
  220. // BLR X16 ; call the tracing trampoline
  221. // ;DATA: 32 bits of function ID
  222. // ;DATA: lower 32 bits of the address of the trampoline
  223. // ;DATA: higher 32 bits of the address of the trampoline
  224. // LDP X0, X30, [SP], #16 ; pop X0 and the link register from the stack
  225. //
  226. OutStreamer->emitCodeAlignment(4);
  227. auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
  228. OutStreamer->emitLabel(CurSled);
  229. auto Target = OutContext.createTempSymbol();
  230. // Emit "B #32" instruction, which jumps over the next 28 bytes.
  231. // The operand has to be the number of 4-byte instructions to jump over,
  232. // including the current instruction.
  233. EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::B).addImm(8));
  234. for (int8_t I = 0; I < NoopsInSledCount; I++)
  235. EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
  236. OutStreamer->emitLabel(Target);
  237. recordSled(CurSled, MI, Kind, 2);
  238. }
  239. void AArch64AsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
  240. Register Reg = MI.getOperand(0).getReg();
  241. bool IsShort =
  242. MI.getOpcode() == AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES;
  243. uint32_t AccessInfo = MI.getOperand(1).getImm();
  244. MCSymbol *&Sym =
  245. HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, IsShort, AccessInfo)];
  246. if (!Sym) {
  247. // FIXME: Make this work on non-ELF.
  248. if (!TM.getTargetTriple().isOSBinFormatELF())
  249. report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");
  250. std::string SymName = "__hwasan_check_x" + utostr(Reg - AArch64::X0) + "_" +
  251. utostr(AccessInfo);
  252. if (IsShort)
  253. SymName += "_short_v2";
  254. Sym = OutContext.getOrCreateSymbol(SymName);
  255. }
  256. EmitToStreamer(*OutStreamer,
  257. MCInstBuilder(AArch64::BL)
  258. .addExpr(MCSymbolRefExpr::create(Sym, OutContext)));
  259. }
  260. void AArch64AsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
  261. if (HwasanMemaccessSymbols.empty())
  262. return;
  263. const Triple &TT = TM.getTargetTriple();
  264. assert(TT.isOSBinFormatELF());
  265. std::unique_ptr<MCSubtargetInfo> STI(
  266. TM.getTarget().createMCSubtargetInfo(TT.str(), "", ""));
  267. assert(STI && "Unable to create subtarget info");
  268. MCSymbol *HwasanTagMismatchV1Sym =
  269. OutContext.getOrCreateSymbol("__hwasan_tag_mismatch");
  270. MCSymbol *HwasanTagMismatchV2Sym =
  271. OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2");
  272. const MCSymbolRefExpr *HwasanTagMismatchV1Ref =
  273. MCSymbolRefExpr::create(HwasanTagMismatchV1Sym, OutContext);
  274. const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
  275. MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext);
  276. for (auto &P : HwasanMemaccessSymbols) {
  277. unsigned Reg = std::get<0>(P.first);
  278. bool IsShort = std::get<1>(P.first);
  279. uint32_t AccessInfo = std::get<2>(P.first);
  280. const MCSymbolRefExpr *HwasanTagMismatchRef =
  281. IsShort ? HwasanTagMismatchV2Ref : HwasanTagMismatchV1Ref;
  282. MCSymbol *Sym = P.second;
  283. bool HasMatchAllTag =
  284. (AccessInfo >> HWASanAccessInfo::HasMatchAllShift) & 1;
  285. uint8_t MatchAllTag =
  286. (AccessInfo >> HWASanAccessInfo::MatchAllShift) & 0xff;
  287. unsigned Size =
  288. 1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf);
  289. bool CompileKernel =
  290. (AccessInfo >> HWASanAccessInfo::CompileKernelShift) & 1;
  291. OutStreamer->SwitchSection(OutContext.getELFSection(
  292. ".text.hot", ELF::SHT_PROGBITS,
  293. ELF::SHF_EXECINSTR | ELF::SHF_ALLOC | ELF::SHF_GROUP, 0,
  294. Sym->getName()));
  295. OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
  296. OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak);
  297. OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden);
  298. OutStreamer->emitLabel(Sym);
  299. OutStreamer->emitInstruction(MCInstBuilder(AArch64::SBFMXri)
  300. .addReg(AArch64::X16)
  301. .addReg(Reg)
  302. .addImm(4)
  303. .addImm(55),
  304. *STI);
  305. OutStreamer->emitInstruction(
  306. MCInstBuilder(AArch64::LDRBBroX)
  307. .addReg(AArch64::W16)
  308. .addReg(IsShort ? AArch64::X20 : AArch64::X9)
  309. .addReg(AArch64::X16)
  310. .addImm(0)
  311. .addImm(0),
  312. *STI);
  313. OutStreamer->emitInstruction(
  314. MCInstBuilder(AArch64::SUBSXrs)
  315. .addReg(AArch64::XZR)
  316. .addReg(AArch64::X16)
  317. .addReg(Reg)
  318. .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSR, 56)),
  319. *STI);
  320. MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
  321. OutStreamer->emitInstruction(
  322. MCInstBuilder(AArch64::Bcc)
  323. .addImm(AArch64CC::NE)
  324. .addExpr(MCSymbolRefExpr::create(HandleMismatchOrPartialSym,
  325. OutContext)),
  326. *STI);
  327. MCSymbol *ReturnSym = OutContext.createTempSymbol();
  328. OutStreamer->emitLabel(ReturnSym);
  329. OutStreamer->emitInstruction(
  330. MCInstBuilder(AArch64::RET).addReg(AArch64::LR), *STI);
  331. OutStreamer->emitLabel(HandleMismatchOrPartialSym);
  332. if (HasMatchAllTag) {
  333. OutStreamer->emitInstruction(MCInstBuilder(AArch64::UBFMXri)
  334. .addReg(AArch64::X16)
  335. .addReg(Reg)
  336. .addImm(56)
  337. .addImm(63),
  338. *STI);
  339. OutStreamer->emitInstruction(MCInstBuilder(AArch64::SUBSXri)
  340. .addReg(AArch64::XZR)
  341. .addReg(AArch64::X16)
  342. .addImm(MatchAllTag)
  343. .addImm(0),
  344. *STI);
  345. OutStreamer->emitInstruction(
  346. MCInstBuilder(AArch64::Bcc)
  347. .addImm(AArch64CC::EQ)
  348. .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
  349. *STI);
  350. }
  351. if (IsShort) {
  352. OutStreamer->emitInstruction(MCInstBuilder(AArch64::SUBSWri)
  353. .addReg(AArch64::WZR)
  354. .addReg(AArch64::W16)
  355. .addImm(15)
  356. .addImm(0),
  357. *STI);
  358. MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
  359. OutStreamer->emitInstruction(
  360. MCInstBuilder(AArch64::Bcc)
  361. .addImm(AArch64CC::HI)
  362. .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
  363. *STI);
  364. OutStreamer->emitInstruction(
  365. MCInstBuilder(AArch64::ANDXri)
  366. .addReg(AArch64::X17)
  367. .addReg(Reg)
  368. .addImm(AArch64_AM::encodeLogicalImmediate(0xf, 64)),
  369. *STI);
  370. if (Size != 1)
  371. OutStreamer->emitInstruction(MCInstBuilder(AArch64::ADDXri)
  372. .addReg(AArch64::X17)
  373. .addReg(AArch64::X17)
  374. .addImm(Size - 1)
  375. .addImm(0),
  376. *STI);
  377. OutStreamer->emitInstruction(MCInstBuilder(AArch64::SUBSWrs)
  378. .addReg(AArch64::WZR)
  379. .addReg(AArch64::W16)
  380. .addReg(AArch64::W17)
  381. .addImm(0),
  382. *STI);
  383. OutStreamer->emitInstruction(
  384. MCInstBuilder(AArch64::Bcc)
  385. .addImm(AArch64CC::LS)
  386. .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
  387. *STI);
  388. OutStreamer->emitInstruction(
  389. MCInstBuilder(AArch64::ORRXri)
  390. .addReg(AArch64::X16)
  391. .addReg(Reg)
  392. .addImm(AArch64_AM::encodeLogicalImmediate(0xf, 64)),
  393. *STI);
  394. OutStreamer->emitInstruction(MCInstBuilder(AArch64::LDRBBui)
  395. .addReg(AArch64::W16)
  396. .addReg(AArch64::X16)
  397. .addImm(0),
  398. *STI);
  399. OutStreamer->emitInstruction(
  400. MCInstBuilder(AArch64::SUBSXrs)
  401. .addReg(AArch64::XZR)
  402. .addReg(AArch64::X16)
  403. .addReg(Reg)
  404. .addImm(AArch64_AM::getShifterImm(AArch64_AM::LSR, 56)),
  405. *STI);
  406. OutStreamer->emitInstruction(
  407. MCInstBuilder(AArch64::Bcc)
  408. .addImm(AArch64CC::EQ)
  409. .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
  410. *STI);
  411. OutStreamer->emitLabel(HandleMismatchSym);
  412. }
  413. OutStreamer->emitInstruction(MCInstBuilder(AArch64::STPXpre)
  414. .addReg(AArch64::SP)
  415. .addReg(AArch64::X0)
  416. .addReg(AArch64::X1)
  417. .addReg(AArch64::SP)
  418. .addImm(-32),
  419. *STI);
  420. OutStreamer->emitInstruction(MCInstBuilder(AArch64::STPXi)
  421. .addReg(AArch64::FP)
  422. .addReg(AArch64::LR)
  423. .addReg(AArch64::SP)
  424. .addImm(29),
  425. *STI);
  426. if (Reg != AArch64::X0)
  427. OutStreamer->emitInstruction(MCInstBuilder(AArch64::ORRXrs)
  428. .addReg(AArch64::X0)
  429. .addReg(AArch64::XZR)
  430. .addReg(Reg)
  431. .addImm(0),
  432. *STI);
  433. OutStreamer->emitInstruction(
  434. MCInstBuilder(AArch64::MOVZXi)
  435. .addReg(AArch64::X1)
  436. .addImm(AccessInfo & HWASanAccessInfo::RuntimeMask)
  437. .addImm(0),
  438. *STI);
  439. if (CompileKernel) {
  440. // The Linux kernel's dynamic loader doesn't support GOT relative
  441. // relocations, but it doesn't support late binding either, so just call
  442. // the function directly.
  443. OutStreamer->emitInstruction(
  444. MCInstBuilder(AArch64::B).addExpr(HwasanTagMismatchRef), *STI);
  445. } else {
  446. // Intentionally load the GOT entry and branch to it, rather than possibly
  447. // late binding the function, which may clobber the registers before we
  448. // have a chance to save them.
  449. OutStreamer->emitInstruction(
  450. MCInstBuilder(AArch64::ADRP)
  451. .addReg(AArch64::X16)
  452. .addExpr(AArch64MCExpr::create(
  453. HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_PAGE,
  454. OutContext)),
  455. *STI);
  456. OutStreamer->emitInstruction(
  457. MCInstBuilder(AArch64::LDRXui)
  458. .addReg(AArch64::X16)
  459. .addReg(AArch64::X16)
  460. .addExpr(AArch64MCExpr::create(
  461. HwasanTagMismatchRef, AArch64MCExpr::VariantKind::VK_GOT_LO12,
  462. OutContext)),
  463. *STI);
  464. OutStreamer->emitInstruction(
  465. MCInstBuilder(AArch64::BR).addReg(AArch64::X16), *STI);
  466. }
  467. }
  468. }
  469. void AArch64AsmPrinter::emitEndOfAsmFile(Module &M) {
  470. EmitHwasanMemaccessSymbols(M);
  471. const Triple &TT = TM.getTargetTriple();
  472. if (TT.isOSBinFormatMachO()) {
  473. // Funny Darwin hack: This flag tells the linker that no global symbols
  474. // contain code that falls through to other global symbols (e.g. the obvious
  475. // implementation of multiple entry points). If this doesn't occur, the
  476. // linker can safely perform dead code stripping. Since LLVM never
  477. // generates code that does this, it is always safe to set.
  478. OutStreamer->emitAssemblerFlag(MCAF_SubsectionsViaSymbols);
  479. }
  480. // Emit stack and fault map information.
  481. emitStackMaps(SM);
  482. FM.serializeToFaultMapSection();
  483. }
  484. void AArch64AsmPrinter::EmitLOHs() {
  485. SmallVector<MCSymbol *, 3> MCArgs;
  486. for (const auto &D : AArch64FI->getLOHContainer()) {
  487. for (const MachineInstr *MI : D.getArgs()) {
  488. MInstToMCSymbol::iterator LabelIt = LOHInstToLabel.find(MI);
  489. assert(LabelIt != LOHInstToLabel.end() &&
  490. "Label hasn't been inserted for LOH related instruction");
  491. MCArgs.push_back(LabelIt->second);
  492. }
  493. OutStreamer->emitLOHDirective(D.getKind(), MCArgs);
  494. MCArgs.clear();
  495. }
  496. }
  497. void AArch64AsmPrinter::emitFunctionBodyEnd() {
  498. if (!AArch64FI->getLOHRelated().empty())
  499. EmitLOHs();
  500. }
  501. /// GetCPISymbol - Return the symbol for the specified constant pool entry.
  502. MCSymbol *AArch64AsmPrinter::GetCPISymbol(unsigned CPID) const {
  503. // Darwin uses a linker-private symbol name for constant-pools (to
  504. // avoid addends on the relocation?), ELF has no such concept and
  505. // uses a normal private symbol.
  506. if (!getDataLayout().getLinkerPrivateGlobalPrefix().empty())
  507. return OutContext.getOrCreateSymbol(
  508. Twine(getDataLayout().getLinkerPrivateGlobalPrefix()) + "CPI" +
  509. Twine(getFunctionNumber()) + "_" + Twine(CPID));
  510. return AsmPrinter::GetCPISymbol(CPID);
  511. }
  512. void AArch64AsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNum,
  513. raw_ostream &O) {
  514. const MachineOperand &MO = MI->getOperand(OpNum);
  515. switch (MO.getType()) {
  516. default:
  517. llvm_unreachable("<unknown operand type>");
  518. case MachineOperand::MO_Register: {
  519. Register Reg = MO.getReg();
  520. assert(Register::isPhysicalRegister(Reg));
  521. assert(!MO.getSubReg() && "Subregs should be eliminated!");
  522. O << AArch64InstPrinter::getRegisterName(Reg);
  523. break;
  524. }
  525. case MachineOperand::MO_Immediate: {
  526. O << MO.getImm();
  527. break;
  528. }
  529. case MachineOperand::MO_GlobalAddress: {
  530. PrintSymbolOperand(MO, O);
  531. break;
  532. }
  533. case MachineOperand::MO_BlockAddress: {
  534. MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
  535. Sym->print(O, MAI);
  536. break;
  537. }
  538. }
  539. }
  540. bool AArch64AsmPrinter::printAsmMRegister(const MachineOperand &MO, char Mode,
  541. raw_ostream &O) {
  542. Register Reg = MO.getReg();
  543. switch (Mode) {
  544. default:
  545. return true; // Unknown mode.
  546. case 'w':
  547. Reg = getWRegFromXReg(Reg);
  548. break;
  549. case 'x':
  550. Reg = getXRegFromWReg(Reg);
  551. break;
  552. }
  553. O << AArch64InstPrinter::getRegisterName(Reg);
  554. return false;
  555. }
  556. // Prints the register in MO using class RC using the offset in the
  557. // new register class. This should not be used for cross class
  558. // printing.
  559. bool AArch64AsmPrinter::printAsmRegInClass(const MachineOperand &MO,
  560. const TargetRegisterClass *RC,
  561. unsigned AltName, raw_ostream &O) {
  562. assert(MO.isReg() && "Should only get here with a register!");
  563. const TargetRegisterInfo *RI = STI->getRegisterInfo();
  564. Register Reg = MO.getReg();
  565. unsigned RegToPrint = RC->getRegister(RI->getEncodingValue(Reg));
  566. if (!RI->regsOverlap(RegToPrint, Reg))
  567. return true;
  568. O << AArch64InstPrinter::getRegisterName(RegToPrint, AltName);
  569. return false;
  570. }
  571. bool AArch64AsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
  572. const char *ExtraCode, raw_ostream &O) {
  573. const MachineOperand &MO = MI->getOperand(OpNum);
  574. // First try the generic code, which knows about modifiers like 'c' and 'n'.
  575. if (!AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O))
  576. return false;
  577. // Does this asm operand have a single letter operand modifier?
  578. if (ExtraCode && ExtraCode[0]) {
  579. if (ExtraCode[1] != 0)
  580. return true; // Unknown modifier.
  581. switch (ExtraCode[0]) {
  582. default:
  583. return true; // Unknown modifier.
  584. case 'w': // Print W register
  585. case 'x': // Print X register
  586. if (MO.isReg())
  587. return printAsmMRegister(MO, ExtraCode[0], O);
  588. if (MO.isImm() && MO.getImm() == 0) {
  589. unsigned Reg = ExtraCode[0] == 'w' ? AArch64::WZR : AArch64::XZR;
  590. O << AArch64InstPrinter::getRegisterName(Reg);
  591. return false;
  592. }
  593. printOperand(MI, OpNum, O);
  594. return false;
  595. case 'b': // Print B register.
  596. case 'h': // Print H register.
  597. case 's': // Print S register.
  598. case 'd': // Print D register.
  599. case 'q': // Print Q register.
  600. case 'z': // Print Z register.
  601. if (MO.isReg()) {
  602. const TargetRegisterClass *RC;
  603. switch (ExtraCode[0]) {
  604. case 'b':
  605. RC = &AArch64::FPR8RegClass;
  606. break;
  607. case 'h':
  608. RC = &AArch64::FPR16RegClass;
  609. break;
  610. case 's':
  611. RC = &AArch64::FPR32RegClass;
  612. break;
  613. case 'd':
  614. RC = &AArch64::FPR64RegClass;
  615. break;
  616. case 'q':
  617. RC = &AArch64::FPR128RegClass;
  618. break;
  619. case 'z':
  620. RC = &AArch64::ZPRRegClass;
  621. break;
  622. default:
  623. return true;
  624. }
  625. return printAsmRegInClass(MO, RC, AArch64::NoRegAltName, O);
  626. }
  627. printOperand(MI, OpNum, O);
  628. return false;
  629. }
  630. }
  631. // According to ARM, we should emit x and v registers unless we have a
  632. // modifier.
  633. if (MO.isReg()) {
  634. Register Reg = MO.getReg();
  635. // If this is a w or x register, print an x register.
  636. if (AArch64::GPR32allRegClass.contains(Reg) ||
  637. AArch64::GPR64allRegClass.contains(Reg))
  638. return printAsmMRegister(MO, 'x', O);
  639. unsigned AltName = AArch64::NoRegAltName;
  640. const TargetRegisterClass *RegClass;
  641. if (AArch64::ZPRRegClass.contains(Reg)) {
  642. RegClass = &AArch64::ZPRRegClass;
  643. } else if (AArch64::PPRRegClass.contains(Reg)) {
  644. RegClass = &AArch64::PPRRegClass;
  645. } else {
  646. RegClass = &AArch64::FPR128RegClass;
  647. AltName = AArch64::vreg;
  648. }
  649. // If this is a b, h, s, d, or q register, print it as a v register.
  650. return printAsmRegInClass(MO, RegClass, AltName, O);
  651. }
  652. printOperand(MI, OpNum, O);
  653. return false;
  654. }
  655. bool AArch64AsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
  656. unsigned OpNum,
  657. const char *ExtraCode,
  658. raw_ostream &O) {
  659. if (ExtraCode && ExtraCode[0] && ExtraCode[0] != 'a')
  660. return true; // Unknown modifier.
  661. const MachineOperand &MO = MI->getOperand(OpNum);
  662. assert(MO.isReg() && "unexpected inline asm memory operand");
  663. O << "[" << AArch64InstPrinter::getRegisterName(MO.getReg()) << "]";
  664. return false;
  665. }
  666. void AArch64AsmPrinter::PrintDebugValueComment(const MachineInstr *MI,
  667. raw_ostream &OS) {
  668. unsigned NOps = MI->getNumOperands();
  669. assert(NOps == 4);
  670. OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
  671. // cast away const; DIetc do not take const operands for some reason.
  672. OS << MI->getDebugVariable()->getName();
  673. OS << " <- ";
  674. // Frame address. Currently handles register +- offset only.
  675. assert(MI->getDebugOperand(0).isReg() && MI->isDebugOffsetImm());
  676. OS << '[';
  677. printOperand(MI, 0, OS);
  678. OS << '+';
  679. printOperand(MI, 1, OS);
  680. OS << ']';
  681. OS << "+";
  682. printOperand(MI, NOps - 2, OS);
  683. }
  684. void AArch64AsmPrinter::emitJumpTableInfo() {
  685. const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
  686. if (!MJTI) return;
  687. const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
  688. if (JT.empty()) return;
  689. const Function &F = MF->getFunction();
  690. const TargetLoweringObjectFile &TLOF = getObjFileLowering();
  691. bool JTInDiffSection =
  692. !STI->isTargetCOFF() ||
  693. !TLOF.shouldPutJumpTableInFunctionSection(
  694. MJTI->getEntryKind() == MachineJumpTableInfo::EK_LabelDifference32,
  695. F);
  696. if (JTInDiffSection) {
  697. // Drop it in the readonly section.
  698. MCSection *ReadOnlySec = TLOF.getSectionForJumpTable(F, TM);
  699. OutStreamer->SwitchSection(ReadOnlySec);
  700. }
  701. auto AFI = MF->getInfo<AArch64FunctionInfo>();
  702. for (unsigned JTI = 0, e = JT.size(); JTI != e; ++JTI) {
  703. const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
  704. // If this jump table was deleted, ignore it.
  705. if (JTBBs.empty()) continue;
  706. unsigned Size = AFI->getJumpTableEntrySize(JTI);
  707. emitAlignment(Align(Size));
  708. OutStreamer->emitLabel(GetJTISymbol(JTI));
  709. const MCSymbol *BaseSym = AArch64FI->getJumpTableEntryPCRelSymbol(JTI);
  710. const MCExpr *Base = MCSymbolRefExpr::create(BaseSym, OutContext);
  711. for (auto *JTBB : JTBBs) {
  712. const MCExpr *Value =
  713. MCSymbolRefExpr::create(JTBB->getSymbol(), OutContext);
  714. // Each entry is:
  715. // .byte/.hword (LBB - Lbase)>>2
  716. // or plain:
  717. // .word LBB - Lbase
  718. Value = MCBinaryExpr::createSub(Value, Base, OutContext);
  719. if (Size != 4)
  720. Value = MCBinaryExpr::createLShr(
  721. Value, MCConstantExpr::create(2, OutContext), OutContext);
  722. OutStreamer->emitValue(Value, Size);
  723. }
  724. }
  725. }
  726. void AArch64AsmPrinter::emitFunctionEntryLabel() {
  727. if (MF->getFunction().getCallingConv() == CallingConv::AArch64_VectorCall ||
  728. MF->getFunction().getCallingConv() ==
  729. CallingConv::AArch64_SVE_VectorCall ||
  730. STI->getRegisterInfo()->hasSVEArgsOrReturn(MF)) {
  731. auto *TS =
  732. static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
  733. TS->emitDirectiveVariantPCS(CurrentFnSym);
  734. }
  735. return AsmPrinter::emitFunctionEntryLabel();
  736. }
  737. /// Small jump tables contain an unsigned byte or half, representing the offset
  738. /// from the lowest-addressed possible destination to the desired basic
  739. /// block. Since all instructions are 4-byte aligned, this is further compressed
  740. /// by counting in instructions rather than bytes (i.e. divided by 4). So, to
  741. /// materialize the correct destination we need:
  742. ///
  743. /// adr xDest, .LBB0_0
  744. /// ldrb wScratch, [xTable, xEntry] (with "lsl #1" for ldrh).
  745. /// add xDest, xDest, xScratch (with "lsl #2" for smaller entries)
  746. void AArch64AsmPrinter::LowerJumpTableDest(llvm::MCStreamer &OutStreamer,
  747. const llvm::MachineInstr &MI) {
  748. Register DestReg = MI.getOperand(0).getReg();
  749. Register ScratchReg = MI.getOperand(1).getReg();
  750. Register ScratchRegW =
  751. STI->getRegisterInfo()->getSubReg(ScratchReg, AArch64::sub_32);
  752. Register TableReg = MI.getOperand(2).getReg();
  753. Register EntryReg = MI.getOperand(3).getReg();
  754. int JTIdx = MI.getOperand(4).getIndex();
  755. int Size = AArch64FI->getJumpTableEntrySize(JTIdx);
  756. // This has to be first because the compression pass based its reachability
  757. // calculations on the start of the JumpTableDest instruction.
  758. auto Label =
  759. MF->getInfo<AArch64FunctionInfo>()->getJumpTableEntryPCRelSymbol(JTIdx);
  760. // If we don't already have a symbol to use as the base, use the ADR
  761. // instruction itself.
  762. if (!Label) {
  763. Label = MF->getContext().createTempSymbol();
  764. AArch64FI->setJumpTableEntryInfo(JTIdx, Size, Label);
  765. OutStreamer.emitLabel(Label);
  766. }
  767. auto LabelExpr = MCSymbolRefExpr::create(Label, MF->getContext());
  768. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADR)
  769. .addReg(DestReg)
  770. .addExpr(LabelExpr));
  771. // Load the number of instruction-steps to offset from the label.
  772. unsigned LdrOpcode;
  773. switch (Size) {
  774. case 1: LdrOpcode = AArch64::LDRBBroX; break;
  775. case 2: LdrOpcode = AArch64::LDRHHroX; break;
  776. case 4: LdrOpcode = AArch64::LDRSWroX; break;
  777. default:
  778. llvm_unreachable("Unknown jump table size");
  779. }
  780. EmitToStreamer(OutStreamer, MCInstBuilder(LdrOpcode)
  781. .addReg(Size == 4 ? ScratchReg : ScratchRegW)
  782. .addReg(TableReg)
  783. .addReg(EntryReg)
  784. .addImm(0)
  785. .addImm(Size == 1 ? 0 : 1));
  786. // Add to the already materialized base label address, multiplying by 4 if
  787. // compressed.
  788. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::ADDXrs)
  789. .addReg(DestReg)
  790. .addReg(DestReg)
  791. .addReg(ScratchReg)
  792. .addImm(Size == 4 ? 0 : 2));
  793. }
  794. void AArch64AsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
  795. const MachineInstr &MI) {
  796. unsigned NumNOPBytes = StackMapOpers(&MI).getNumPatchBytes();
  797. auto &Ctx = OutStreamer.getContext();
  798. MCSymbol *MILabel = Ctx.createTempSymbol();
  799. OutStreamer.emitLabel(MILabel);
  800. SM.recordStackMap(*MILabel, MI);
  801. assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
  802. // Scan ahead to trim the shadow.
  803. const MachineBasicBlock &MBB = *MI.getParent();
  804. MachineBasicBlock::const_iterator MII(MI);
  805. ++MII;
  806. while (NumNOPBytes > 0) {
  807. if (MII == MBB.end() || MII->isCall() ||
  808. MII->getOpcode() == AArch64::DBG_VALUE ||
  809. MII->getOpcode() == TargetOpcode::PATCHPOINT ||
  810. MII->getOpcode() == TargetOpcode::STACKMAP)
  811. break;
  812. ++MII;
  813. NumNOPBytes -= 4;
  814. }
  815. // Emit nops.
  816. for (unsigned i = 0; i < NumNOPBytes; i += 4)
  817. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
  818. }
  819. // Lower a patchpoint of the form:
  820. // [<def>], <id>, <numBytes>, <target>, <numArgs>
  821. void AArch64AsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,
  822. const MachineInstr &MI) {
  823. auto &Ctx = OutStreamer.getContext();
  824. MCSymbol *MILabel = Ctx.createTempSymbol();
  825. OutStreamer.emitLabel(MILabel);
  826. SM.recordPatchPoint(*MILabel, MI);
  827. PatchPointOpers Opers(&MI);
  828. int64_t CallTarget = Opers.getCallTarget().getImm();
  829. unsigned EncodedBytes = 0;
  830. if (CallTarget) {
  831. assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&
  832. "High 16 bits of call target should be zero.");
  833. Register ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg();
  834. EncodedBytes = 16;
  835. // Materialize the jump address:
  836. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVZXi)
  837. .addReg(ScratchReg)
  838. .addImm((CallTarget >> 32) & 0xFFFF)
  839. .addImm(32));
  840. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKXi)
  841. .addReg(ScratchReg)
  842. .addReg(ScratchReg)
  843. .addImm((CallTarget >> 16) & 0xFFFF)
  844. .addImm(16));
  845. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::MOVKXi)
  846. .addReg(ScratchReg)
  847. .addReg(ScratchReg)
  848. .addImm(CallTarget & 0xFFFF)
  849. .addImm(0));
  850. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::BLR).addReg(ScratchReg));
  851. }
  852. // Emit padding.
  853. unsigned NumBytes = Opers.getNumPatchBytes();
  854. assert(NumBytes >= EncodedBytes &&
  855. "Patchpoint can't request size less than the length of a call.");
  856. assert((NumBytes - EncodedBytes) % 4 == 0 &&
  857. "Invalid number of NOP bytes requested!");
  858. for (unsigned i = EncodedBytes; i < NumBytes; i += 4)
  859. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
  860. }
  861. void AArch64AsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,
  862. const MachineInstr &MI) {
  863. StatepointOpers SOpers(&MI);
  864. if (unsigned PatchBytes = SOpers.getNumPatchBytes()) {
  865. assert(PatchBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
  866. for (unsigned i = 0; i < PatchBytes; i += 4)
  867. EmitToStreamer(OutStreamer, MCInstBuilder(AArch64::HINT).addImm(0));
  868. } else {
  869. // Lower call target and choose correct opcode
  870. const MachineOperand &CallTarget = SOpers.getCallTarget();
  871. MCOperand CallTargetMCOp;
  872. unsigned CallOpcode;
  873. switch (CallTarget.getType()) {
  874. case MachineOperand::MO_GlobalAddress:
  875. case MachineOperand::MO_ExternalSymbol:
  876. MCInstLowering.lowerOperand(CallTarget, CallTargetMCOp);
  877. CallOpcode = AArch64::BL;
  878. break;
  879. case MachineOperand::MO_Immediate:
  880. CallTargetMCOp = MCOperand::createImm(CallTarget.getImm());
  881. CallOpcode = AArch64::BL;
  882. break;
  883. case MachineOperand::MO_Register:
  884. CallTargetMCOp = MCOperand::createReg(CallTarget.getReg());
  885. CallOpcode = AArch64::BLR;
  886. break;
  887. default:
  888. llvm_unreachable("Unsupported operand type in statepoint call target");
  889. break;
  890. }
  891. EmitToStreamer(OutStreamer,
  892. MCInstBuilder(CallOpcode).addOperand(CallTargetMCOp));
  893. }
  894. auto &Ctx = OutStreamer.getContext();
  895. MCSymbol *MILabel = Ctx.createTempSymbol();
  896. OutStreamer.emitLabel(MILabel);
  897. SM.recordStatepoint(*MILabel, MI);
  898. }
  899. void AArch64AsmPrinter::LowerFAULTING_OP(const MachineInstr &FaultingMI) {
  900. // FAULTING_LOAD_OP <def>, <faltinf type>, <MBB handler>,
  901. // <opcode>, <operands>
  902. Register DefRegister = FaultingMI.getOperand(0).getReg();
  903. FaultMaps::FaultKind FK =
  904. static_cast<FaultMaps::FaultKind>(FaultingMI.getOperand(1).getImm());
  905. MCSymbol *HandlerLabel = FaultingMI.getOperand(2).getMBB()->getSymbol();
  906. unsigned Opcode = FaultingMI.getOperand(3).getImm();
  907. unsigned OperandsBeginIdx = 4;
  908. auto &Ctx = OutStreamer->getContext();
  909. MCSymbol *FaultingLabel = Ctx.createTempSymbol();
  910. OutStreamer->emitLabel(FaultingLabel);
  911. assert(FK < FaultMaps::FaultKindMax && "Invalid Faulting Kind!");
  912. FM.recordFaultingOp(FK, FaultingLabel, HandlerLabel);
  913. MCInst MI;
  914. MI.setOpcode(Opcode);
  915. if (DefRegister != (Register)0)
  916. MI.addOperand(MCOperand::createReg(DefRegister));
  917. for (auto I = FaultingMI.operands_begin() + OperandsBeginIdx,
  918. E = FaultingMI.operands_end();
  919. I != E; ++I) {
  920. MCOperand Dest;
  921. lowerOperand(*I, Dest);
  922. MI.addOperand(Dest);
  923. }
  924. OutStreamer->AddComment("on-fault: " + HandlerLabel->getName());
  925. OutStreamer->emitInstruction(MI, getSubtargetInfo());
  926. }
  927. void AArch64AsmPrinter::EmitFMov0(const MachineInstr &MI) {
  928. Register DestReg = MI.getOperand(0).getReg();
  929. if (STI->hasZeroCycleZeroingFP() && !STI->hasZeroCycleZeroingFPWorkaround()) {
  930. // Convert H/S/D register to corresponding Q register
  931. if (AArch64::H0 <= DestReg && DestReg <= AArch64::H31)
  932. DestReg = AArch64::Q0 + (DestReg - AArch64::H0);
  933. else if (AArch64::S0 <= DestReg && DestReg <= AArch64::S31)
  934. DestReg = AArch64::Q0 + (DestReg - AArch64::S0);
  935. else {
  936. assert(AArch64::D0 <= DestReg && DestReg <= AArch64::D31);
  937. DestReg = AArch64::Q0 + (DestReg - AArch64::D0);
  938. }
  939. MCInst MOVI;
  940. MOVI.setOpcode(AArch64::MOVIv2d_ns);
  941. MOVI.addOperand(MCOperand::createReg(DestReg));
  942. MOVI.addOperand(MCOperand::createImm(0));
  943. EmitToStreamer(*OutStreamer, MOVI);
  944. } else {
  945. MCInst FMov;
  946. switch (MI.getOpcode()) {
  947. default: llvm_unreachable("Unexpected opcode");
  948. case AArch64::FMOVH0:
  949. FMov.setOpcode(AArch64::FMOVWHr);
  950. FMov.addOperand(MCOperand::createReg(DestReg));
  951. FMov.addOperand(MCOperand::createReg(AArch64::WZR));
  952. break;
  953. case AArch64::FMOVS0:
  954. FMov.setOpcode(AArch64::FMOVWSr);
  955. FMov.addOperand(MCOperand::createReg(DestReg));
  956. FMov.addOperand(MCOperand::createReg(AArch64::WZR));
  957. break;
  958. case AArch64::FMOVD0:
  959. FMov.setOpcode(AArch64::FMOVXDr);
  960. FMov.addOperand(MCOperand::createReg(DestReg));
  961. FMov.addOperand(MCOperand::createReg(AArch64::XZR));
  962. break;
  963. }
  964. EmitToStreamer(*OutStreamer, FMov);
  965. }
  966. }
  967. // Simple pseudo-instructions have their lowering (with expansion to real
  968. // instructions) auto-generated.
  969. #include "AArch64GenMCPseudoLowering.inc"
  970. void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
  971. // Do any auto-generated pseudo lowerings.
  972. if (emitPseudoExpansionLowering(*OutStreamer, MI))
  973. return;
  974. if (AArch64FI->getLOHRelated().count(MI)) {
  975. // Generate a label for LOH related instruction
  976. MCSymbol *LOHLabel = createTempSymbol("loh");
  977. // Associate the instruction with the label
  978. LOHInstToLabel[MI] = LOHLabel;
  979. OutStreamer->emitLabel(LOHLabel);
  980. }
  981. AArch64TargetStreamer *TS =
  982. static_cast<AArch64TargetStreamer *>(OutStreamer->getTargetStreamer());
  983. // Do any manual lowerings.
  984. switch (MI->getOpcode()) {
  985. default:
  986. break;
  987. case AArch64::HINT: {
  988. // CurrentPatchableFunctionEntrySym can be CurrentFnBegin only for
  989. // -fpatchable-function-entry=N,0. The entry MBB is guaranteed to be
  990. // non-empty. If MI is the initial BTI, place the
  991. // __patchable_function_entries label after BTI.
  992. if (CurrentPatchableFunctionEntrySym &&
  993. CurrentPatchableFunctionEntrySym == CurrentFnBegin &&
  994. MI == &MF->front().front()) {
  995. int64_t Imm = MI->getOperand(0).getImm();
  996. if ((Imm & 32) && (Imm & 6)) {
  997. MCInst Inst;
  998. MCInstLowering.Lower(MI, Inst);
  999. EmitToStreamer(*OutStreamer, Inst);
  1000. CurrentPatchableFunctionEntrySym = createTempSymbol("patch");
  1001. OutStreamer->emitLabel(CurrentPatchableFunctionEntrySym);
  1002. return;
  1003. }
  1004. }
  1005. break;
  1006. }
  1007. case AArch64::MOVMCSym: {
  1008. Register DestReg = MI->getOperand(0).getReg();
  1009. const MachineOperand &MO_Sym = MI->getOperand(1);
  1010. MachineOperand Hi_MOSym(MO_Sym), Lo_MOSym(MO_Sym);
  1011. MCOperand Hi_MCSym, Lo_MCSym;
  1012. Hi_MOSym.setTargetFlags(AArch64II::MO_G1 | AArch64II::MO_S);
  1013. Lo_MOSym.setTargetFlags(AArch64II::MO_G0 | AArch64II::MO_NC);
  1014. MCInstLowering.lowerOperand(Hi_MOSym, Hi_MCSym);
  1015. MCInstLowering.lowerOperand(Lo_MOSym, Lo_MCSym);
  1016. MCInst MovZ;
  1017. MovZ.setOpcode(AArch64::MOVZXi);
  1018. MovZ.addOperand(MCOperand::createReg(DestReg));
  1019. MovZ.addOperand(Hi_MCSym);
  1020. MovZ.addOperand(MCOperand::createImm(16));
  1021. EmitToStreamer(*OutStreamer, MovZ);
  1022. MCInst MovK;
  1023. MovK.setOpcode(AArch64::MOVKXi);
  1024. MovK.addOperand(MCOperand::createReg(DestReg));
  1025. MovK.addOperand(MCOperand::createReg(DestReg));
  1026. MovK.addOperand(Lo_MCSym);
  1027. MovK.addOperand(MCOperand::createImm(0));
  1028. EmitToStreamer(*OutStreamer, MovK);
  1029. return;
  1030. }
  1031. case AArch64::MOVIv2d_ns:
  1032. // If the target has <rdar://problem/16473581>, lower this
  1033. // instruction to movi.16b instead.
  1034. if (STI->hasZeroCycleZeroingFPWorkaround() &&
  1035. MI->getOperand(1).getImm() == 0) {
  1036. MCInst TmpInst;
  1037. TmpInst.setOpcode(AArch64::MOVIv16b_ns);
  1038. TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
  1039. TmpInst.addOperand(MCOperand::createImm(MI->getOperand(1).getImm()));
  1040. EmitToStreamer(*OutStreamer, TmpInst);
  1041. return;
  1042. }
  1043. break;
  1044. case AArch64::DBG_VALUE: {
  1045. if (isVerbose() && OutStreamer->hasRawTextSupport()) {
  1046. SmallString<128> TmpStr;
  1047. raw_svector_ostream OS(TmpStr);
  1048. PrintDebugValueComment(MI, OS);
  1049. OutStreamer->emitRawText(StringRef(OS.str()));
  1050. }
  1051. return;
  1052. case AArch64::EMITBKEY: {
  1053. ExceptionHandling ExceptionHandlingType = MAI->getExceptionHandlingType();
  1054. if (ExceptionHandlingType != ExceptionHandling::DwarfCFI &&
  1055. ExceptionHandlingType != ExceptionHandling::ARM)
  1056. return;
  1057. if (needsCFIMoves() == CFI_M_None)
  1058. return;
  1059. OutStreamer->emitCFIBKeyFrame();
  1060. return;
  1061. }
  1062. }
  1063. // Tail calls use pseudo instructions so they have the proper code-gen
  1064. // attributes (isCall, isReturn, etc.). We lower them to the real
  1065. // instruction here.
  1066. case AArch64::TCRETURNri:
  1067. case AArch64::TCRETURNriBTI:
  1068. case AArch64::TCRETURNriALL: {
  1069. MCInst TmpInst;
  1070. TmpInst.setOpcode(AArch64::BR);
  1071. TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
  1072. EmitToStreamer(*OutStreamer, TmpInst);
  1073. return;
  1074. }
  1075. case AArch64::TCRETURNdi: {
  1076. MCOperand Dest;
  1077. MCInstLowering.lowerOperand(MI->getOperand(0), Dest);
  1078. MCInst TmpInst;
  1079. TmpInst.setOpcode(AArch64::B);
  1080. TmpInst.addOperand(Dest);
  1081. EmitToStreamer(*OutStreamer, TmpInst);
  1082. return;
  1083. }
  1084. case AArch64::SpeculationBarrierISBDSBEndBB: {
  1085. // Print DSB SYS + ISB
  1086. MCInst TmpInstDSB;
  1087. TmpInstDSB.setOpcode(AArch64::DSB);
  1088. TmpInstDSB.addOperand(MCOperand::createImm(0xf));
  1089. EmitToStreamer(*OutStreamer, TmpInstDSB);
  1090. MCInst TmpInstISB;
  1091. TmpInstISB.setOpcode(AArch64::ISB);
  1092. TmpInstISB.addOperand(MCOperand::createImm(0xf));
  1093. EmitToStreamer(*OutStreamer, TmpInstISB);
  1094. return;
  1095. }
  1096. case AArch64::SpeculationBarrierSBEndBB: {
  1097. // Print SB
  1098. MCInst TmpInstSB;
  1099. TmpInstSB.setOpcode(AArch64::SB);
  1100. EmitToStreamer(*OutStreamer, TmpInstSB);
  1101. return;
  1102. }
  1103. case AArch64::TLSDESC_CALLSEQ: {
  1104. /// lower this to:
  1105. /// adrp x0, :tlsdesc:var
  1106. /// ldr x1, [x0, #:tlsdesc_lo12:var]
  1107. /// add x0, x0, #:tlsdesc_lo12:var
  1108. /// .tlsdesccall var
  1109. /// blr x1
  1110. /// (TPIDR_EL0 offset now in x0)
  1111. const MachineOperand &MO_Sym = MI->getOperand(0);
  1112. MachineOperand MO_TLSDESC_LO12(MO_Sym), MO_TLSDESC(MO_Sym);
  1113. MCOperand Sym, SymTLSDescLo12, SymTLSDesc;
  1114. MO_TLSDESC_LO12.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGEOFF);
  1115. MO_TLSDESC.setTargetFlags(AArch64II::MO_TLS | AArch64II::MO_PAGE);
  1116. MCInstLowering.lowerOperand(MO_Sym, Sym);
  1117. MCInstLowering.lowerOperand(MO_TLSDESC_LO12, SymTLSDescLo12);
  1118. MCInstLowering.lowerOperand(MO_TLSDESC, SymTLSDesc);
  1119. MCInst Adrp;
  1120. Adrp.setOpcode(AArch64::ADRP);
  1121. Adrp.addOperand(MCOperand::createReg(AArch64::X0));
  1122. Adrp.addOperand(SymTLSDesc);
  1123. EmitToStreamer(*OutStreamer, Adrp);
  1124. MCInst Ldr;
  1125. if (STI->isTargetILP32()) {
  1126. Ldr.setOpcode(AArch64::LDRWui);
  1127. Ldr.addOperand(MCOperand::createReg(AArch64::W1));
  1128. } else {
  1129. Ldr.setOpcode(AArch64::LDRXui);
  1130. Ldr.addOperand(MCOperand::createReg(AArch64::X1));
  1131. }
  1132. Ldr.addOperand(MCOperand::createReg(AArch64::X0));
  1133. Ldr.addOperand(SymTLSDescLo12);
  1134. Ldr.addOperand(MCOperand::createImm(0));
  1135. EmitToStreamer(*OutStreamer, Ldr);
  1136. MCInst Add;
  1137. if (STI->isTargetILP32()) {
  1138. Add.setOpcode(AArch64::ADDWri);
  1139. Add.addOperand(MCOperand::createReg(AArch64::W0));
  1140. Add.addOperand(MCOperand::createReg(AArch64::W0));
  1141. } else {
  1142. Add.setOpcode(AArch64::ADDXri);
  1143. Add.addOperand(MCOperand::createReg(AArch64::X0));
  1144. Add.addOperand(MCOperand::createReg(AArch64::X0));
  1145. }
  1146. Add.addOperand(SymTLSDescLo12);
  1147. Add.addOperand(MCOperand::createImm(AArch64_AM::getShiftValue(0)));
  1148. EmitToStreamer(*OutStreamer, Add);
  1149. // Emit a relocation-annotation. This expands to no code, but requests
  1150. // the following instruction gets an R_AARCH64_TLSDESC_CALL.
  1151. MCInst TLSDescCall;
  1152. TLSDescCall.setOpcode(AArch64::TLSDESCCALL);
  1153. TLSDescCall.addOperand(Sym);
  1154. EmitToStreamer(*OutStreamer, TLSDescCall);
  1155. MCInst Blr;
  1156. Blr.setOpcode(AArch64::BLR);
  1157. Blr.addOperand(MCOperand::createReg(AArch64::X1));
  1158. EmitToStreamer(*OutStreamer, Blr);
  1159. return;
  1160. }
  1161. case AArch64::JumpTableDest32:
  1162. case AArch64::JumpTableDest16:
  1163. case AArch64::JumpTableDest8:
  1164. LowerJumpTableDest(*OutStreamer, *MI);
  1165. return;
  1166. case AArch64::FMOVH0:
  1167. case AArch64::FMOVS0:
  1168. case AArch64::FMOVD0:
  1169. EmitFMov0(*MI);
  1170. return;
  1171. case TargetOpcode::STACKMAP:
  1172. return LowerSTACKMAP(*OutStreamer, SM, *MI);
  1173. case TargetOpcode::PATCHPOINT:
  1174. return LowerPATCHPOINT(*OutStreamer, SM, *MI);
  1175. case TargetOpcode::STATEPOINT:
  1176. return LowerSTATEPOINT(*OutStreamer, SM, *MI);
  1177. case TargetOpcode::FAULTING_OP:
  1178. return LowerFAULTING_OP(*MI);
  1179. case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
  1180. LowerPATCHABLE_FUNCTION_ENTER(*MI);
  1181. return;
  1182. case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
  1183. LowerPATCHABLE_FUNCTION_EXIT(*MI);
  1184. return;
  1185. case TargetOpcode::PATCHABLE_TAIL_CALL:
  1186. LowerPATCHABLE_TAIL_CALL(*MI);
  1187. return;
  1188. case AArch64::HWASAN_CHECK_MEMACCESS:
  1189. case AArch64::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
  1190. LowerHWASAN_CHECK_MEMACCESS(*MI);
  1191. return;
  1192. case AArch64::SEH_StackAlloc:
  1193. TS->EmitARM64WinCFIAllocStack(MI->getOperand(0).getImm());
  1194. return;
  1195. case AArch64::SEH_SaveFPLR:
  1196. TS->EmitARM64WinCFISaveFPLR(MI->getOperand(0).getImm());
  1197. return;
  1198. case AArch64::SEH_SaveFPLR_X:
  1199. assert(MI->getOperand(0).getImm() < 0 &&
  1200. "Pre increment SEH opcode must have a negative offset");
  1201. TS->EmitARM64WinCFISaveFPLRX(-MI->getOperand(0).getImm());
  1202. return;
  1203. case AArch64::SEH_SaveReg:
  1204. TS->EmitARM64WinCFISaveReg(MI->getOperand(0).getImm(),
  1205. MI->getOperand(1).getImm());
  1206. return;
  1207. case AArch64::SEH_SaveReg_X:
  1208. assert(MI->getOperand(1).getImm() < 0 &&
  1209. "Pre increment SEH opcode must have a negative offset");
  1210. TS->EmitARM64WinCFISaveRegX(MI->getOperand(0).getImm(),
  1211. -MI->getOperand(1).getImm());
  1212. return;
  1213. case AArch64::SEH_SaveRegP:
  1214. if (MI->getOperand(1).getImm() == 30 && MI->getOperand(0).getImm() >= 19 &&
  1215. MI->getOperand(0).getImm() <= 28) {
  1216. assert((MI->getOperand(0).getImm() - 19) % 2 == 0 &&
  1217. "Register paired with LR must be odd");
  1218. TS->EmitARM64WinCFISaveLRPair(MI->getOperand(0).getImm(),
  1219. MI->getOperand(2).getImm());
  1220. return;
  1221. }
  1222. assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
  1223. "Non-consecutive registers not allowed for save_regp");
  1224. TS->EmitARM64WinCFISaveRegP(MI->getOperand(0).getImm(),
  1225. MI->getOperand(2).getImm());
  1226. return;
  1227. case AArch64::SEH_SaveRegP_X:
  1228. assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
  1229. "Non-consecutive registers not allowed for save_regp_x");
  1230. assert(MI->getOperand(2).getImm() < 0 &&
  1231. "Pre increment SEH opcode must have a negative offset");
  1232. TS->EmitARM64WinCFISaveRegPX(MI->getOperand(0).getImm(),
  1233. -MI->getOperand(2).getImm());
  1234. return;
  1235. case AArch64::SEH_SaveFReg:
  1236. TS->EmitARM64WinCFISaveFReg(MI->getOperand(0).getImm(),
  1237. MI->getOperand(1).getImm());
  1238. return;
  1239. case AArch64::SEH_SaveFReg_X:
  1240. assert(MI->getOperand(1).getImm() < 0 &&
  1241. "Pre increment SEH opcode must have a negative offset");
  1242. TS->EmitARM64WinCFISaveFRegX(MI->getOperand(0).getImm(),
  1243. -MI->getOperand(1).getImm());
  1244. return;
  1245. case AArch64::SEH_SaveFRegP:
  1246. assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
  1247. "Non-consecutive registers not allowed for save_regp");
  1248. TS->EmitARM64WinCFISaveFRegP(MI->getOperand(0).getImm(),
  1249. MI->getOperand(2).getImm());
  1250. return;
  1251. case AArch64::SEH_SaveFRegP_X:
  1252. assert((MI->getOperand(1).getImm() - MI->getOperand(0).getImm() == 1) &&
  1253. "Non-consecutive registers not allowed for save_regp_x");
  1254. assert(MI->getOperand(2).getImm() < 0 &&
  1255. "Pre increment SEH opcode must have a negative offset");
  1256. TS->EmitARM64WinCFISaveFRegPX(MI->getOperand(0).getImm(),
  1257. -MI->getOperand(2).getImm());
  1258. return;
  1259. case AArch64::SEH_SetFP:
  1260. TS->EmitARM64WinCFISetFP();
  1261. return;
  1262. case AArch64::SEH_AddFP:
  1263. TS->EmitARM64WinCFIAddFP(MI->getOperand(0).getImm());
  1264. return;
  1265. case AArch64::SEH_Nop:
  1266. TS->EmitARM64WinCFINop();
  1267. return;
  1268. case AArch64::SEH_PrologEnd:
  1269. TS->EmitARM64WinCFIPrologEnd();
  1270. return;
  1271. case AArch64::SEH_EpilogStart:
  1272. TS->EmitARM64WinCFIEpilogStart();
  1273. return;
  1274. case AArch64::SEH_EpilogEnd:
  1275. TS->EmitARM64WinCFIEpilogEnd();
  1276. return;
  1277. }
  1278. // Finally, do the automated lowerings for everything else.
  1279. MCInst TmpInst;
  1280. MCInstLowering.Lower(MI, TmpInst);
  1281. EmitToStreamer(*OutStreamer, TmpInst);
  1282. }
  1283. // Force static initialization.
  1284. extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeAArch64AsmPrinter() {
  1285. RegisterAsmPrinter<AArch64AsmPrinter> X(getTheAArch64leTarget());
  1286. RegisterAsmPrinter<AArch64AsmPrinter> Y(getTheAArch64beTarget());
  1287. RegisterAsmPrinter<AArch64AsmPrinter> Z(getTheARM64Target());
  1288. RegisterAsmPrinter<AArch64AsmPrinter> W(getTheARM64_32Target());
  1289. RegisterAsmPrinter<AArch64AsmPrinter> V(getTheAArch64_32Target());
  1290. }