RISCVAsmPrinter.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. //===-- RISCVAsmPrinter.cpp - RISCV 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 RISCV assembly language.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "MCTargetDesc/RISCVInstPrinter.h"
  14. #include "MCTargetDesc/RISCVMCExpr.h"
  15. #include "MCTargetDesc/RISCVTargetStreamer.h"
  16. #include "RISCV.h"
  17. #include "RISCVMachineFunctionInfo.h"
  18. #include "RISCVTargetMachine.h"
  19. #include "TargetInfo/RISCVTargetInfo.h"
  20. #include "llvm/ADT/Statistic.h"
  21. #include "llvm/BinaryFormat/ELF.h"
  22. #include "llvm/CodeGen/AsmPrinter.h"
  23. #include "llvm/CodeGen/MachineConstantPool.h"
  24. #include "llvm/CodeGen/MachineFunctionPass.h"
  25. #include "llvm/CodeGen/MachineInstr.h"
  26. #include "llvm/CodeGen/MachineModuleInfo.h"
  27. #include "llvm/MC/MCAsmInfo.h"
  28. #include "llvm/MC/MCContext.h"
  29. #include "llvm/MC/MCInst.h"
  30. #include "llvm/MC/MCInstBuilder.h"
  31. #include "llvm/MC/MCObjectFileInfo.h"
  32. #include "llvm/MC/MCSectionELF.h"
  33. #include "llvm/MC/MCStreamer.h"
  34. #include "llvm/MC/MCSymbol.h"
  35. #include "llvm/MC/TargetRegistry.h"
  36. #include "llvm/Support/raw_ostream.h"
  37. #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
  38. using namespace llvm;
  39. #define DEBUG_TYPE "asm-printer"
  40. STATISTIC(RISCVNumInstrsCompressed,
  41. "Number of RISC-V Compressed instructions emitted");
  42. namespace {
  43. class RISCVAsmPrinter : public AsmPrinter {
  44. const RISCVSubtarget *STI;
  45. public:
  46. explicit RISCVAsmPrinter(TargetMachine &TM,
  47. std::unique_ptr<MCStreamer> Streamer)
  48. : AsmPrinter(TM, std::move(Streamer)) {}
  49. StringRef getPassName() const override { return "RISCV Assembly Printer"; }
  50. bool runOnMachineFunction(MachineFunction &MF) override;
  51. void emitInstruction(const MachineInstr *MI) override;
  52. bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
  53. const char *ExtraCode, raw_ostream &OS) override;
  54. bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
  55. const char *ExtraCode, raw_ostream &OS) override;
  56. void EmitToStreamer(MCStreamer &S, const MCInst &Inst);
  57. bool emitPseudoExpansionLowering(MCStreamer &OutStreamer,
  58. const MachineInstr *MI);
  59. typedef std::tuple<unsigned, uint32_t> HwasanMemaccessTuple;
  60. std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;
  61. void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);
  62. void EmitHwasanMemaccessSymbols(Module &M);
  63. // Wrapper needed for tblgenned pseudo lowering.
  64. bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const {
  65. return lowerRISCVMachineOperandToMCOperand(MO, MCOp, *this);
  66. }
  67. void emitStartOfAsmFile(Module &M) override;
  68. void emitEndOfAsmFile(Module &M) override;
  69. void emitFunctionEntryLabel() override;
  70. private:
  71. void emitAttributes();
  72. };
  73. }
  74. void RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) {
  75. MCInst CInst;
  76. bool Res = RISCVRVC::compress(CInst, Inst, *STI);
  77. if (Res)
  78. ++RISCVNumInstrsCompressed;
  79. AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst);
  80. }
  81. // Simple pseudo-instructions have their lowering (with expansion to real
  82. // instructions) auto-generated.
  83. #include "RISCVGenMCPseudoLowering.inc"
  84. void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {
  85. RISCV_MC::verifyInstructionPredicates(MI->getOpcode(),
  86. getSubtargetInfo().getFeatureBits());
  87. // Do any auto-generated pseudo lowerings.
  88. if (emitPseudoExpansionLowering(*OutStreamer, MI))
  89. return;
  90. switch (MI->getOpcode()) {
  91. case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:
  92. LowerHWASAN_CHECK_MEMACCESS(*MI);
  93. return;
  94. }
  95. MCInst TmpInst;
  96. if (!lowerRISCVMachineInstrToMCInst(MI, TmpInst, *this))
  97. EmitToStreamer(*OutStreamer, TmpInst);
  98. }
  99. bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
  100. const char *ExtraCode, raw_ostream &OS) {
  101. // First try the generic code, which knows about modifiers like 'c' and 'n'.
  102. if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
  103. return false;
  104. const MachineOperand &MO = MI->getOperand(OpNo);
  105. if (ExtraCode && ExtraCode[0]) {
  106. if (ExtraCode[1] != 0)
  107. return true; // Unknown modifier.
  108. switch (ExtraCode[0]) {
  109. default:
  110. return true; // Unknown modifier.
  111. case 'z': // Print zero register if zero, regular printing otherwise.
  112. if (MO.isImm() && MO.getImm() == 0) {
  113. OS << RISCVInstPrinter::getRegisterName(RISCV::X0);
  114. return false;
  115. }
  116. break;
  117. case 'i': // Literal 'i' if operand is not a register.
  118. if (!MO.isReg())
  119. OS << 'i';
  120. return false;
  121. }
  122. }
  123. switch (MO.getType()) {
  124. case MachineOperand::MO_Immediate:
  125. OS << MO.getImm();
  126. return false;
  127. case MachineOperand::MO_Register:
  128. OS << RISCVInstPrinter::getRegisterName(MO.getReg());
  129. return false;
  130. case MachineOperand::MO_GlobalAddress:
  131. PrintSymbolOperand(MO, OS);
  132. return false;
  133. case MachineOperand::MO_BlockAddress: {
  134. MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
  135. Sym->print(OS, MAI);
  136. return false;
  137. }
  138. default:
  139. break;
  140. }
  141. return true;
  142. }
  143. bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
  144. unsigned OpNo,
  145. const char *ExtraCode,
  146. raw_ostream &OS) {
  147. if (!ExtraCode) {
  148. const MachineOperand &MO = MI->getOperand(OpNo);
  149. // For now, we only support register memory operands in registers and
  150. // assume there is no addend
  151. if (!MO.isReg())
  152. return true;
  153. OS << "0(" << RISCVInstPrinter::getRegisterName(MO.getReg()) << ")";
  154. return false;
  155. }
  156. return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
  157. }
  158. bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
  159. STI = &MF.getSubtarget<RISCVSubtarget>();
  160. SetupMachineFunction(MF);
  161. emitFunctionBody();
  162. return false;
  163. }
  164. void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) {
  165. RISCVTargetStreamer &RTS =
  166. static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
  167. if (const MDString *ModuleTargetABI =
  168. dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi")))
  169. RTS.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI->getString()));
  170. if (TM.getTargetTriple().isOSBinFormatELF())
  171. emitAttributes();
  172. }
  173. void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
  174. RISCVTargetStreamer &RTS =
  175. static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
  176. if (TM.getTargetTriple().isOSBinFormatELF())
  177. RTS.finishAttributeSection();
  178. EmitHwasanMemaccessSymbols(M);
  179. }
  180. void RISCVAsmPrinter::emitAttributes() {
  181. RISCVTargetStreamer &RTS =
  182. static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
  183. // Use MCSubtargetInfo from TargetMachine. Individual functions may have
  184. // attributes that differ from other functions in the module and we have no
  185. // way to know which function is correct.
  186. RTS.emitTargetAttributes(*TM.getMCSubtargetInfo());
  187. }
  188. void RISCVAsmPrinter::emitFunctionEntryLabel() {
  189. const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>();
  190. if (RMFI->isVectorCall()) {
  191. auto &RTS =
  192. static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
  193. RTS.emitDirectiveVariantCC(*CurrentFnSym);
  194. }
  195. return AsmPrinter::emitFunctionEntryLabel();
  196. }
  197. // Force static initialization.
  198. extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter() {
  199. RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target());
  200. RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target());
  201. }
  202. void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
  203. Register Reg = MI.getOperand(0).getReg();
  204. uint32_t AccessInfo = MI.getOperand(1).getImm();
  205. MCSymbol *&Sym =
  206. HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)];
  207. if (!Sym) {
  208. // FIXME: Make this work on non-ELF.
  209. if (!TM.getTargetTriple().isOSBinFormatELF())
  210. report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");
  211. std::string SymName = "__hwasan_check_x" + utostr(Reg - RISCV::X0) + "_" +
  212. utostr(AccessInfo) + "_short";
  213. Sym = OutContext.getOrCreateSymbol(SymName);
  214. }
  215. auto Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, OutContext);
  216. auto Expr = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, OutContext);
  217. EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
  218. }
  219. void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
  220. if (HwasanMemaccessSymbols.empty())
  221. return;
  222. assert(TM.getTargetTriple().isOSBinFormatELF());
  223. // Use MCSubtargetInfo from TargetMachine. Individual functions may have
  224. // attributes that differ from other functions in the module and we have no
  225. // way to know which function is correct.
  226. const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();
  227. MCSymbol *HwasanTagMismatchV2Sym =
  228. OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2");
  229. // Annotate symbol as one having incompatible calling convention, so
  230. // run-time linkers can instead eagerly bind this function.
  231. auto &RTS =
  232. static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
  233. RTS.emitDirectiveVariantCC(*HwasanTagMismatchV2Sym);
  234. const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
  235. MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext);
  236. auto Expr = RISCVMCExpr::create(HwasanTagMismatchV2Ref,
  237. RISCVMCExpr::VK_RISCV_CALL, OutContext);
  238. for (auto &P : HwasanMemaccessSymbols) {
  239. unsigned Reg = std::get<0>(P.first);
  240. uint32_t AccessInfo = std::get<1>(P.first);
  241. MCSymbol *Sym = P.second;
  242. unsigned Size =
  243. 1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf);
  244. OutStreamer->switchSection(OutContext.getELFSection(
  245. ".text.hot", ELF::SHT_PROGBITS,
  246. ELF::SHF_EXECINSTR | ELF::SHF_ALLOC | ELF::SHF_GROUP, 0, Sym->getName(),
  247. /*IsComdat=*/true));
  248. OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
  249. OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak);
  250. OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden);
  251. OutStreamer->emitLabel(Sym);
  252. // Extract shadow offset from ptr
  253. OutStreamer->emitInstruction(
  254. MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(Reg).addImm(8),
  255. MCSTI);
  256. OutStreamer->emitInstruction(MCInstBuilder(RISCV::SRLI)
  257. .addReg(RISCV::X6)
  258. .addReg(RISCV::X6)
  259. .addImm(12),
  260. MCSTI);
  261. // load shadow tag in X6, X5 contains shadow base
  262. OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADD)
  263. .addReg(RISCV::X6)
  264. .addReg(RISCV::X5)
  265. .addReg(RISCV::X6),
  266. MCSTI);
  267. OutStreamer->emitInstruction(
  268. MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
  269. MCSTI);
  270. // Extract tag from X5 and compare it with loaded tag from shadow
  271. OutStreamer->emitInstruction(
  272. MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(Reg).addImm(56),
  273. MCSTI);
  274. MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
  275. // X7 contains tag from memory, while X6 contains tag from the pointer
  276. OutStreamer->emitInstruction(
  277. MCInstBuilder(RISCV::BNE)
  278. .addReg(RISCV::X7)
  279. .addReg(RISCV::X6)
  280. .addExpr(MCSymbolRefExpr::create(HandleMismatchOrPartialSym,
  281. OutContext)),
  282. MCSTI);
  283. MCSymbol *ReturnSym = OutContext.createTempSymbol();
  284. OutStreamer->emitLabel(ReturnSym);
  285. OutStreamer->emitInstruction(MCInstBuilder(RISCV::JALR)
  286. .addReg(RISCV::X0)
  287. .addReg(RISCV::X1)
  288. .addImm(0),
  289. MCSTI);
  290. OutStreamer->emitLabel(HandleMismatchOrPartialSym);
  291. OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
  292. .addReg(RISCV::X28)
  293. .addReg(RISCV::X0)
  294. .addImm(16),
  295. MCSTI);
  296. MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
  297. OutStreamer->emitInstruction(
  298. MCInstBuilder(RISCV::BGEU)
  299. .addReg(RISCV::X6)
  300. .addReg(RISCV::X28)
  301. .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
  302. MCSTI);
  303. OutStreamer->emitInstruction(
  304. MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(Reg).addImm(0xF),
  305. MCSTI);
  306. if (Size != 1)
  307. OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
  308. .addReg(RISCV::X28)
  309. .addReg(RISCV::X28)
  310. .addImm(Size - 1),
  311. MCSTI);
  312. OutStreamer->emitInstruction(
  313. MCInstBuilder(RISCV::BGE)
  314. .addReg(RISCV::X28)
  315. .addReg(RISCV::X6)
  316. .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
  317. MCSTI);
  318. OutStreamer->emitInstruction(
  319. MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(Reg).addImm(0xF),
  320. MCSTI);
  321. OutStreamer->emitInstruction(
  322. MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
  323. MCSTI);
  324. OutStreamer->emitInstruction(
  325. MCInstBuilder(RISCV::BEQ)
  326. .addReg(RISCV::X6)
  327. .addReg(RISCV::X7)
  328. .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
  329. MCSTI);
  330. OutStreamer->emitLabel(HandleMismatchSym);
  331. // | Previous stack frames... |
  332. // +=================================+ <-- [SP + 256]
  333. // | ... |
  334. // | |
  335. // | Stack frame space for x12 - x31.|
  336. // | |
  337. // | ... |
  338. // +---------------------------------+ <-- [SP + 96]
  339. // | Saved x11(arg1), as |
  340. // | __hwasan_check_* clobbers it. |
  341. // +---------------------------------+ <-- [SP + 88]
  342. // | Saved x10(arg0), as |
  343. // | __hwasan_check_* clobbers it. |
  344. // +---------------------------------+ <-- [SP + 80]
  345. // | |
  346. // | Stack frame space for x9. |
  347. // +---------------------------------+ <-- [SP + 72]
  348. // | |
  349. // | Saved x8(fp), as |
  350. // | __hwasan_check_* clobbers it. |
  351. // +---------------------------------+ <-- [SP + 64]
  352. // | ... |
  353. // | |
  354. // | Stack frame space for x2 - x7. |
  355. // | |
  356. // | ... |
  357. // +---------------------------------+ <-- [SP + 16]
  358. // | Return address (x1) for caller |
  359. // | of __hwasan_check_*. |
  360. // +---------------------------------+ <-- [SP + 8]
  361. // | Reserved place for x0, possibly |
  362. // | junk, since we don't save it. |
  363. // +---------------------------------+ <-- [x2 / SP]
  364. // Adjust sp
  365. OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
  366. .addReg(RISCV::X2)
  367. .addReg(RISCV::X2)
  368. .addImm(-256),
  369. MCSTI);
  370. // store x10(arg0) by new sp
  371. OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD)
  372. .addReg(RISCV::X10)
  373. .addReg(RISCV::X2)
  374. .addImm(8 * 10),
  375. MCSTI);
  376. // store x11(arg1) by new sp
  377. OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD)
  378. .addReg(RISCV::X11)
  379. .addReg(RISCV::X2)
  380. .addImm(8 * 11),
  381. MCSTI);
  382. // store x8(fp) by new sp
  383. OutStreamer->emitInstruction(
  384. MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 *
  385. 8),
  386. MCSTI);
  387. // store x1(ra) by new sp
  388. OutStreamer->emitInstruction(
  389. MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 *
  390. 8),
  391. MCSTI);
  392. if (Reg != RISCV::X10)
  393. OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI)
  394. .addReg(RISCV::X10)
  395. .addReg(Reg)
  396. .addImm(0),
  397. MCSTI);
  398. OutStreamer->emitInstruction(
  399. MCInstBuilder(RISCV::ADDI)
  400. .addReg(RISCV::X11)
  401. .addReg(RISCV::X0)
  402. .addImm(AccessInfo & HWASanAccessInfo::RuntimeMask),
  403. MCSTI);
  404. OutStreamer->emitInstruction(MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr),
  405. MCSTI);
  406. }
  407. }