1 //===-- RISCVAsmPrinter.cpp - RISC-V 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 RISC-V assembly language. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "MCTargetDesc/RISCVBaseInfo.h" 15 #include "MCTargetDesc/RISCVInstPrinter.h" 16 #include "MCTargetDesc/RISCVMCExpr.h" 17 #include "MCTargetDesc/RISCVTargetStreamer.h" 18 #include "RISCV.h" 19 #include "RISCVMachineFunctionInfo.h" 20 #include "RISCVTargetMachine.h" 21 #include "TargetInfo/RISCVTargetInfo.h" 22 #include "llvm/ADT/APInt.h" 23 #include "llvm/ADT/Statistic.h" 24 #include "llvm/BinaryFormat/ELF.h" 25 #include "llvm/CodeGen/AsmPrinter.h" 26 #include "llvm/CodeGen/MachineConstantPool.h" 27 #include "llvm/CodeGen/MachineFunctionPass.h" 28 #include "llvm/CodeGen/MachineInstr.h" 29 #include "llvm/CodeGen/MachineModuleInfo.h" 30 #include "llvm/MC/MCAsmInfo.h" 31 #include "llvm/MC/MCContext.h" 32 #include "llvm/MC/MCInst.h" 33 #include "llvm/MC/MCInstBuilder.h" 34 #include "llvm/MC/MCObjectFileInfo.h" 35 #include "llvm/MC/MCSectionELF.h" 36 #include "llvm/MC/MCStreamer.h" 37 #include "llvm/MC/MCSymbol.h" 38 #include "llvm/MC/TargetRegistry.h" 39 #include "llvm/Support/raw_ostream.h" 40 #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h" 41 42 using namespace llvm; 43 44 #define DEBUG_TYPE "asm-printer" 45 46 STATISTIC(RISCVNumInstrsCompressed, 47 "Number of RISC-V Compressed instructions emitted"); 48 49 namespace { 50 class RISCVAsmPrinter : public AsmPrinter { 51 const RISCVSubtarget *STI; 52 53 public: 54 explicit RISCVAsmPrinter(TargetMachine &TM, 55 std::unique_ptr<MCStreamer> Streamer) 56 : AsmPrinter(TM, std::move(Streamer)) {} 57 58 StringRef getPassName() const override { return "RISC-V Assembly Printer"; } 59 60 bool runOnMachineFunction(MachineFunction &MF) override; 61 62 void emitInstruction(const MachineInstr *MI) override; 63 64 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 65 const char *ExtraCode, raw_ostream &OS) override; 66 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 67 const char *ExtraCode, raw_ostream &OS) override; 68 69 void EmitToStreamer(MCStreamer &S, const MCInst &Inst); 70 bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, 71 const MachineInstr *MI); 72 73 typedef std::tuple<unsigned, uint32_t> HwasanMemaccessTuple; 74 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols; 75 void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI); 76 void LowerKCFI_CHECK(const MachineInstr &MI); 77 void EmitHwasanMemaccessSymbols(Module &M); 78 79 // Wrapper needed for tblgenned pseudo lowering. 80 bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const; 81 82 void emitStartOfAsmFile(Module &M) override; 83 void emitEndOfAsmFile(Module &M) override; 84 85 void emitFunctionEntryLabel() override; 86 87 private: 88 void emitAttributes(); 89 90 void emitNTLHint(const MachineInstr *MI); 91 92 bool lowerToMCInst(const MachineInstr *MI, MCInst &OutMI); 93 }; 94 } 95 96 void RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) { 97 MCInst CInst; 98 bool Res = RISCVRVC::compress(CInst, Inst, *STI); 99 if (Res) 100 ++RISCVNumInstrsCompressed; 101 AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst); 102 } 103 104 // Simple pseudo-instructions have their lowering (with expansion to real 105 // instructions) auto-generated. 106 #include "RISCVGenMCPseudoLowering.inc" 107 108 // If the target supports Zihintntl and the instruction has a nontemporal 109 // MachineMemOperand, emit an NTLH hint instruction before it. 110 void RISCVAsmPrinter::emitNTLHint(const MachineInstr *MI) { 111 if (!STI->hasStdExtZihintntl()) 112 return; 113 114 if (MI->memoperands_empty()) 115 return; 116 117 MachineMemOperand *MMO = *(MI->memoperands_begin()); 118 if (!MMO->isNonTemporal()) 119 return; 120 121 unsigned NontemporalMode = 0; 122 if (MMO->getFlags() & MONontemporalBit0) 123 NontemporalMode += 0b1; 124 if (MMO->getFlags() & MONontemporalBit1) 125 NontemporalMode += 0b10; 126 127 MCInst Hint; 128 if (STI->hasStdExtCOrZca() && STI->enableRVCHintInstrs()) 129 Hint.setOpcode(RISCV::C_ADD_HINT); 130 else 131 Hint.setOpcode(RISCV::ADD); 132 133 Hint.addOperand(MCOperand::createReg(RISCV::X0)); 134 Hint.addOperand(MCOperand::createReg(RISCV::X0)); 135 Hint.addOperand(MCOperand::createReg(RISCV::X2 + NontemporalMode)); 136 137 EmitToStreamer(*OutStreamer, Hint); 138 } 139 140 void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) { 141 RISCV_MC::verifyInstructionPredicates(MI->getOpcode(), 142 getSubtargetInfo().getFeatureBits()); 143 144 emitNTLHint(MI); 145 146 // Do any auto-generated pseudo lowerings. 147 if (emitPseudoExpansionLowering(*OutStreamer, MI)) 148 return; 149 150 151 switch (MI->getOpcode()) { 152 case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES: 153 LowerHWASAN_CHECK_MEMACCESS(*MI); 154 return; 155 case RISCV::KCFI_CHECK: 156 LowerKCFI_CHECK(*MI); 157 return; 158 case RISCV::PseudoRVVInitUndefM1: 159 case RISCV::PseudoRVVInitUndefM2: 160 case RISCV::PseudoRVVInitUndefM4: 161 case RISCV::PseudoRVVInitUndefM8: 162 return; 163 } 164 165 MCInst OutInst; 166 if (!lowerToMCInst(MI, OutInst)) 167 EmitToStreamer(*OutStreamer, OutInst); 168 } 169 170 bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 171 const char *ExtraCode, raw_ostream &OS) { 172 // First try the generic code, which knows about modifiers like 'c' and 'n'. 173 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS)) 174 return false; 175 176 const MachineOperand &MO = MI->getOperand(OpNo); 177 if (ExtraCode && ExtraCode[0]) { 178 if (ExtraCode[1] != 0) 179 return true; // Unknown modifier. 180 181 switch (ExtraCode[0]) { 182 default: 183 return true; // Unknown modifier. 184 case 'z': // Print zero register if zero, regular printing otherwise. 185 if (MO.isImm() && MO.getImm() == 0) { 186 OS << RISCVInstPrinter::getRegisterName(RISCV::X0); 187 return false; 188 } 189 break; 190 case 'i': // Literal 'i' if operand is not a register. 191 if (!MO.isReg()) 192 OS << 'i'; 193 return false; 194 } 195 } 196 197 switch (MO.getType()) { 198 case MachineOperand::MO_Immediate: 199 OS << MO.getImm(); 200 return false; 201 case MachineOperand::MO_Register: 202 OS << RISCVInstPrinter::getRegisterName(MO.getReg()); 203 return false; 204 case MachineOperand::MO_GlobalAddress: 205 PrintSymbolOperand(MO, OS); 206 return false; 207 case MachineOperand::MO_BlockAddress: { 208 MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress()); 209 Sym->print(OS, MAI); 210 return false; 211 } 212 default: 213 break; 214 } 215 216 return true; 217 } 218 219 bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 220 unsigned OpNo, 221 const char *ExtraCode, 222 raw_ostream &OS) { 223 if (ExtraCode) 224 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS); 225 226 const MachineOperand &AddrReg = MI->getOperand(OpNo); 227 assert(MI->getNumOperands() > OpNo + 1 && "Expected additional operand"); 228 const MachineOperand &Offset = MI->getOperand(OpNo + 1); 229 // All memory operands should have a register and an immediate operand (see 230 // RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand). 231 if (!AddrReg.isReg()) 232 return true; 233 if (!Offset.isImm() && !Offset.isGlobal()) 234 return true; 235 236 MCOperand MCO; 237 if (!lowerOperand(Offset, MCO)) 238 return true; 239 240 if (Offset.isImm()) 241 OS << MCO.getImm(); 242 else if (Offset.isGlobal()) 243 OS << *MCO.getExpr(); 244 OS << "(" << RISCVInstPrinter::getRegisterName(AddrReg.getReg()) << ")"; 245 return false; 246 } 247 248 bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 249 STI = &MF.getSubtarget<RISCVSubtarget>(); 250 251 SetupMachineFunction(MF); 252 emitFunctionBody(); 253 return false; 254 } 255 256 void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) { 257 RISCVTargetStreamer &RTS = 258 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); 259 if (const MDString *ModuleTargetABI = 260 dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi"))) 261 RTS.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI->getString())); 262 if (TM.getTargetTriple().isOSBinFormatELF()) 263 emitAttributes(); 264 } 265 266 void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) { 267 RISCVTargetStreamer &RTS = 268 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); 269 270 if (TM.getTargetTriple().isOSBinFormatELF()) 271 RTS.finishAttributeSection(); 272 EmitHwasanMemaccessSymbols(M); 273 } 274 275 void RISCVAsmPrinter::emitAttributes() { 276 RISCVTargetStreamer &RTS = 277 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); 278 // Use MCSubtargetInfo from TargetMachine. Individual functions may have 279 // attributes that differ from other functions in the module and we have no 280 // way to know which function is correct. 281 RTS.emitTargetAttributes(*TM.getMCSubtargetInfo(), /*EmitStackAlign*/ true); 282 } 283 284 void RISCVAsmPrinter::emitFunctionEntryLabel() { 285 const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>(); 286 if (RMFI->isVectorCall()) { 287 auto &RTS = 288 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); 289 RTS.emitDirectiveVariantCC(*CurrentFnSym); 290 } 291 return AsmPrinter::emitFunctionEntryLabel(); 292 } 293 294 // Force static initialization. 295 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter() { 296 RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target()); 297 RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target()); 298 } 299 300 void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) { 301 Register Reg = MI.getOperand(0).getReg(); 302 uint32_t AccessInfo = MI.getOperand(1).getImm(); 303 MCSymbol *&Sym = 304 HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)]; 305 if (!Sym) { 306 // FIXME: Make this work on non-ELF. 307 if (!TM.getTargetTriple().isOSBinFormatELF()) 308 report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF"); 309 310 std::string SymName = "__hwasan_check_x" + utostr(Reg - RISCV::X0) + "_" + 311 utostr(AccessInfo) + "_short"; 312 Sym = OutContext.getOrCreateSymbol(SymName); 313 } 314 auto Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, OutContext); 315 auto Expr = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, OutContext); 316 317 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr)); 318 } 319 320 void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) { 321 Register AddrReg = MI.getOperand(0).getReg(); 322 assert(std::next(MI.getIterator())->isCall() && 323 "KCFI_CHECK not followed by a call instruction"); 324 assert(std::next(MI.getIterator())->getOperand(0).getReg() == AddrReg && 325 "KCFI_CHECK call target doesn't match call operand"); 326 327 // Temporary registers for comparing the hashes. If a register is used 328 // for the call target, or reserved by the user, we can clobber another 329 // temporary register as the check is immediately followed by the 330 // call. The check defaults to X6/X7, but can fall back to X28-X31 if 331 // needed. 332 unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7}; 333 unsigned NextReg = RISCV::X28; 334 auto isRegAvailable = [&](unsigned Reg) { 335 return Reg != AddrReg && !STI->isRegisterReservedByUser(Reg); 336 }; 337 for (auto &Reg : ScratchRegs) { 338 if (isRegAvailable(Reg)) 339 continue; 340 while (!isRegAvailable(NextReg)) 341 ++NextReg; 342 Reg = NextReg++; 343 if (Reg > RISCV::X31) 344 report_fatal_error("Unable to find scratch registers for KCFI_CHECK"); 345 } 346 347 if (AddrReg == RISCV::X0) { 348 // Checking X0 makes no sense. Instead of emitting a load, zero 349 // ScratchRegs[0]. 350 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI) 351 .addReg(ScratchRegs[0]) 352 .addReg(RISCV::X0) 353 .addImm(0)); 354 } else { 355 // Adjust the offset for patchable-function-prefix. This assumes that 356 // patchable-function-prefix is the same for all functions. 357 int NopSize = STI->hasStdExtCOrZca() ? 2 : 4; 358 int64_t PrefixNops = 0; 359 (void)MI.getMF() 360 ->getFunction() 361 .getFnAttribute("patchable-function-prefix") 362 .getValueAsString() 363 .getAsInteger(10, PrefixNops); 364 365 // Load the target function type hash. 366 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW) 367 .addReg(ScratchRegs[0]) 368 .addReg(AddrReg) 369 .addImm(-(PrefixNops * NopSize + 4))); 370 } 371 372 // Load the expected 32-bit type hash. 373 const int64_t Type = MI.getOperand(1).getImm(); 374 const int64_t Hi20 = ((Type + 0x800) >> 12) & 0xFFFFF; 375 const int64_t Lo12 = SignExtend64<12>(Type); 376 if (Hi20) { 377 EmitToStreamer( 378 *OutStreamer, 379 MCInstBuilder(RISCV::LUI).addReg(ScratchRegs[1]).addImm(Hi20)); 380 } 381 if (Lo12 || Hi20 == 0) { 382 EmitToStreamer(*OutStreamer, 383 MCInstBuilder((STI->hasFeature(RISCV::Feature64Bit) && Hi20) 384 ? RISCV::ADDIW 385 : RISCV::ADDI) 386 .addReg(ScratchRegs[1]) 387 .addReg(ScratchRegs[1]) 388 .addImm(Lo12)); 389 } 390 391 // Compare the hashes and trap if there's a mismatch. 392 MCSymbol *Pass = OutContext.createTempSymbol(); 393 EmitToStreamer(*OutStreamer, 394 MCInstBuilder(RISCV::BEQ) 395 .addReg(ScratchRegs[0]) 396 .addReg(ScratchRegs[1]) 397 .addExpr(MCSymbolRefExpr::create(Pass, OutContext))); 398 399 MCSymbol *Trap = OutContext.createTempSymbol(); 400 OutStreamer->emitLabel(Trap); 401 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::EBREAK)); 402 emitKCFITrapEntry(*MI.getMF(), Trap); 403 OutStreamer->emitLabel(Pass); 404 } 405 406 void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) { 407 if (HwasanMemaccessSymbols.empty()) 408 return; 409 410 assert(TM.getTargetTriple().isOSBinFormatELF()); 411 // Use MCSubtargetInfo from TargetMachine. Individual functions may have 412 // attributes that differ from other functions in the module and we have no 413 // way to know which function is correct. 414 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo(); 415 416 MCSymbol *HwasanTagMismatchV2Sym = 417 OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2"); 418 // Annotate symbol as one having incompatible calling convention, so 419 // run-time linkers can instead eagerly bind this function. 420 auto &RTS = 421 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); 422 RTS.emitDirectiveVariantCC(*HwasanTagMismatchV2Sym); 423 424 const MCSymbolRefExpr *HwasanTagMismatchV2Ref = 425 MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext); 426 auto Expr = RISCVMCExpr::create(HwasanTagMismatchV2Ref, 427 RISCVMCExpr::VK_RISCV_CALL, OutContext); 428 429 for (auto &P : HwasanMemaccessSymbols) { 430 unsigned Reg = std::get<0>(P.first); 431 uint32_t AccessInfo = std::get<1>(P.first); 432 MCSymbol *Sym = P.second; 433 434 unsigned Size = 435 1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf); 436 OutStreamer->switchSection(OutContext.getELFSection( 437 ".text.hot", ELF::SHT_PROGBITS, 438 ELF::SHF_EXECINSTR | ELF::SHF_ALLOC | ELF::SHF_GROUP, 0, Sym->getName(), 439 /*IsComdat=*/true)); 440 441 OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction); 442 OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak); 443 OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden); 444 OutStreamer->emitLabel(Sym); 445 446 // Extract shadow offset from ptr 447 OutStreamer->emitInstruction( 448 MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(Reg).addImm(8), 449 MCSTI); 450 OutStreamer->emitInstruction(MCInstBuilder(RISCV::SRLI) 451 .addReg(RISCV::X6) 452 .addReg(RISCV::X6) 453 .addImm(12), 454 MCSTI); 455 // load shadow tag in X6, X5 contains shadow base 456 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADD) 457 .addReg(RISCV::X6) 458 .addReg(RISCV::X5) 459 .addReg(RISCV::X6), 460 MCSTI); 461 OutStreamer->emitInstruction( 462 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0), 463 MCSTI); 464 // Extract tag from X5 and compare it with loaded tag from shadow 465 OutStreamer->emitInstruction( 466 MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(Reg).addImm(56), 467 MCSTI); 468 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol(); 469 // X7 contains tag from memory, while X6 contains tag from the pointer 470 OutStreamer->emitInstruction( 471 MCInstBuilder(RISCV::BNE) 472 .addReg(RISCV::X7) 473 .addReg(RISCV::X6) 474 .addExpr(MCSymbolRefExpr::create(HandleMismatchOrPartialSym, 475 OutContext)), 476 MCSTI); 477 MCSymbol *ReturnSym = OutContext.createTempSymbol(); 478 OutStreamer->emitLabel(ReturnSym); 479 OutStreamer->emitInstruction(MCInstBuilder(RISCV::JALR) 480 .addReg(RISCV::X0) 481 .addReg(RISCV::X1) 482 .addImm(0), 483 MCSTI); 484 OutStreamer->emitLabel(HandleMismatchOrPartialSym); 485 486 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI) 487 .addReg(RISCV::X28) 488 .addReg(RISCV::X0) 489 .addImm(16), 490 MCSTI); 491 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol(); 492 OutStreamer->emitInstruction( 493 MCInstBuilder(RISCV::BGEU) 494 .addReg(RISCV::X6) 495 .addReg(RISCV::X28) 496 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)), 497 MCSTI); 498 499 OutStreamer->emitInstruction( 500 MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(Reg).addImm(0xF), 501 MCSTI); 502 503 if (Size != 1) 504 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI) 505 .addReg(RISCV::X28) 506 .addReg(RISCV::X28) 507 .addImm(Size - 1), 508 MCSTI); 509 OutStreamer->emitInstruction( 510 MCInstBuilder(RISCV::BGE) 511 .addReg(RISCV::X28) 512 .addReg(RISCV::X6) 513 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)), 514 MCSTI); 515 516 OutStreamer->emitInstruction( 517 MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(Reg).addImm(0xF), 518 MCSTI); 519 OutStreamer->emitInstruction( 520 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0), 521 MCSTI); 522 OutStreamer->emitInstruction( 523 MCInstBuilder(RISCV::BEQ) 524 .addReg(RISCV::X6) 525 .addReg(RISCV::X7) 526 .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)), 527 MCSTI); 528 529 OutStreamer->emitLabel(HandleMismatchSym); 530 531 // | Previous stack frames... | 532 // +=================================+ <-- [SP + 256] 533 // | ... | 534 // | | 535 // | Stack frame space for x12 - x31.| 536 // | | 537 // | ... | 538 // +---------------------------------+ <-- [SP + 96] 539 // | Saved x11(arg1), as | 540 // | __hwasan_check_* clobbers it. | 541 // +---------------------------------+ <-- [SP + 88] 542 // | Saved x10(arg0), as | 543 // | __hwasan_check_* clobbers it. | 544 // +---------------------------------+ <-- [SP + 80] 545 // | | 546 // | Stack frame space for x9. | 547 // +---------------------------------+ <-- [SP + 72] 548 // | | 549 // | Saved x8(fp), as | 550 // | __hwasan_check_* clobbers it. | 551 // +---------------------------------+ <-- [SP + 64] 552 // | ... | 553 // | | 554 // | Stack frame space for x2 - x7. | 555 // | | 556 // | ... | 557 // +---------------------------------+ <-- [SP + 16] 558 // | Return address (x1) for caller | 559 // | of __hwasan_check_*. | 560 // +---------------------------------+ <-- [SP + 8] 561 // | Reserved place for x0, possibly | 562 // | junk, since we don't save it. | 563 // +---------------------------------+ <-- [x2 / SP] 564 565 // Adjust sp 566 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI) 567 .addReg(RISCV::X2) 568 .addReg(RISCV::X2) 569 .addImm(-256), 570 MCSTI); 571 572 // store x10(arg0) by new sp 573 OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD) 574 .addReg(RISCV::X10) 575 .addReg(RISCV::X2) 576 .addImm(8 * 10), 577 MCSTI); 578 // store x11(arg1) by new sp 579 OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD) 580 .addReg(RISCV::X11) 581 .addReg(RISCV::X2) 582 .addImm(8 * 11), 583 MCSTI); 584 585 // store x8(fp) by new sp 586 OutStreamer->emitInstruction( 587 MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 * 588 8), 589 MCSTI); 590 // store x1(ra) by new sp 591 OutStreamer->emitInstruction( 592 MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 * 593 8), 594 MCSTI); 595 if (Reg != RISCV::X10) 596 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI) 597 .addReg(RISCV::X10) 598 .addReg(Reg) 599 .addImm(0), 600 MCSTI); 601 OutStreamer->emitInstruction( 602 MCInstBuilder(RISCV::ADDI) 603 .addReg(RISCV::X11) 604 .addReg(RISCV::X0) 605 .addImm(AccessInfo & HWASanAccessInfo::RuntimeMask), 606 MCSTI); 607 608 OutStreamer->emitInstruction(MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr), 609 MCSTI); 610 } 611 } 612 613 static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, 614 const AsmPrinter &AP) { 615 MCContext &Ctx = AP.OutContext; 616 RISCVMCExpr::VariantKind Kind; 617 618 switch (MO.getTargetFlags()) { 619 default: 620 llvm_unreachable("Unknown target flag on GV operand"); 621 case RISCVII::MO_None: 622 Kind = RISCVMCExpr::VK_RISCV_None; 623 break; 624 case RISCVII::MO_CALL: 625 Kind = RISCVMCExpr::VK_RISCV_CALL; 626 break; 627 case RISCVII::MO_PLT: 628 Kind = RISCVMCExpr::VK_RISCV_CALL_PLT; 629 break; 630 case RISCVII::MO_LO: 631 Kind = RISCVMCExpr::VK_RISCV_LO; 632 break; 633 case RISCVII::MO_HI: 634 Kind = RISCVMCExpr::VK_RISCV_HI; 635 break; 636 case RISCVII::MO_PCREL_LO: 637 Kind = RISCVMCExpr::VK_RISCV_PCREL_LO; 638 break; 639 case RISCVII::MO_PCREL_HI: 640 Kind = RISCVMCExpr::VK_RISCV_PCREL_HI; 641 break; 642 case RISCVII::MO_GOT_HI: 643 Kind = RISCVMCExpr::VK_RISCV_GOT_HI; 644 break; 645 case RISCVII::MO_TPREL_LO: 646 Kind = RISCVMCExpr::VK_RISCV_TPREL_LO; 647 break; 648 case RISCVII::MO_TPREL_HI: 649 Kind = RISCVMCExpr::VK_RISCV_TPREL_HI; 650 break; 651 case RISCVII::MO_TPREL_ADD: 652 Kind = RISCVMCExpr::VK_RISCV_TPREL_ADD; 653 break; 654 case RISCVII::MO_TLS_GOT_HI: 655 Kind = RISCVMCExpr::VK_RISCV_TLS_GOT_HI; 656 break; 657 case RISCVII::MO_TLS_GD_HI: 658 Kind = RISCVMCExpr::VK_RISCV_TLS_GD_HI; 659 break; 660 } 661 662 const MCExpr *ME = 663 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); 664 665 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) 666 ME = MCBinaryExpr::createAdd( 667 ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 668 669 if (Kind != RISCVMCExpr::VK_RISCV_None) 670 ME = RISCVMCExpr::create(ME, Kind, Ctx); 671 return MCOperand::createExpr(ME); 672 } 673 674 bool RISCVAsmPrinter::lowerOperand(const MachineOperand &MO, 675 MCOperand &MCOp) const { 676 switch (MO.getType()) { 677 default: 678 report_fatal_error("lowerOperand: unknown operand type"); 679 case MachineOperand::MO_Register: 680 // Ignore all implicit register operands. 681 if (MO.isImplicit()) 682 return false; 683 MCOp = MCOperand::createReg(MO.getReg()); 684 break; 685 case MachineOperand::MO_RegisterMask: 686 // Regmasks are like implicit defs. 687 return false; 688 case MachineOperand::MO_Immediate: 689 MCOp = MCOperand::createImm(MO.getImm()); 690 break; 691 case MachineOperand::MO_MachineBasicBlock: 692 MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), *this); 693 break; 694 case MachineOperand::MO_GlobalAddress: 695 MCOp = lowerSymbolOperand(MO, getSymbolPreferLocal(*MO.getGlobal()), *this); 696 break; 697 case MachineOperand::MO_BlockAddress: 698 MCOp = lowerSymbolOperand(MO, GetBlockAddressSymbol(MO.getBlockAddress()), 699 *this); 700 break; 701 case MachineOperand::MO_ExternalSymbol: 702 MCOp = lowerSymbolOperand(MO, GetExternalSymbolSymbol(MO.getSymbolName()), 703 *this); 704 break; 705 case MachineOperand::MO_ConstantPoolIndex: 706 MCOp = lowerSymbolOperand(MO, GetCPISymbol(MO.getIndex()), *this); 707 break; 708 case MachineOperand::MO_JumpTableIndex: 709 MCOp = lowerSymbolOperand(MO, GetJTISymbol(MO.getIndex()), *this); 710 break; 711 case MachineOperand::MO_MCSymbol: 712 MCOp = lowerSymbolOperand(MO, MO.getMCSymbol(), *this); 713 break; 714 } 715 return true; 716 } 717 718 static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI, 719 MCInst &OutMI) { 720 const RISCVVPseudosTable::PseudoInfo *RVV = 721 RISCVVPseudosTable::getPseudoInfo(MI->getOpcode()); 722 if (!RVV) 723 return false; 724 725 OutMI.setOpcode(RVV->BaseInstr); 726 727 const MachineBasicBlock *MBB = MI->getParent(); 728 assert(MBB && "MI expected to be in a basic block"); 729 const MachineFunction *MF = MBB->getParent(); 730 assert(MF && "MBB expected to be in a machine function"); 731 732 const RISCVSubtarget &Subtarget = MF->getSubtarget<RISCVSubtarget>(); 733 const TargetInstrInfo *TII = Subtarget.getInstrInfo(); 734 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); 735 assert(TRI && "TargetRegisterInfo expected"); 736 737 const MCInstrDesc &MCID = MI->getDesc(); 738 uint64_t TSFlags = MCID.TSFlags; 739 unsigned NumOps = MI->getNumExplicitOperands(); 740 741 // Skip policy, VL and SEW operands which are the last operands if present. 742 if (RISCVII::hasVecPolicyOp(TSFlags)) 743 --NumOps; 744 if (RISCVII::hasVLOp(TSFlags)) 745 --NumOps; 746 if (RISCVII::hasSEWOp(TSFlags)) 747 --NumOps; 748 if (RISCVII::hasRoundModeOp(TSFlags)) 749 --NumOps; 750 751 bool hasVLOutput = RISCV::isFaultFirstLoad(*MI); 752 for (unsigned OpNo = 0; OpNo != NumOps; ++OpNo) { 753 const MachineOperand &MO = MI->getOperand(OpNo); 754 // Skip vl ouput. It should be the second output. 755 if (hasVLOutput && OpNo == 1) 756 continue; 757 758 // Skip merge op. It should be the first operand after the defs. 759 if (OpNo == MI->getNumExplicitDefs() && MO.isReg() && MO.isTied()) { 760 assert(MCID.getOperandConstraint(OpNo, MCOI::TIED_TO) == 0 && 761 "Expected tied to first def."); 762 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode()); 763 // Skip if the next operand in OutMI is not supposed to be tied. Unless it 764 // is a _TIED instruction. 765 if (OutMCID.getOperandConstraint(OutMI.getNumOperands(), MCOI::TIED_TO) < 766 0 && 767 !RISCVII::isTiedPseudo(TSFlags)) 768 continue; 769 } 770 771 MCOperand MCOp; 772 switch (MO.getType()) { 773 default: 774 llvm_unreachable("Unknown operand type"); 775 case MachineOperand::MO_Register: { 776 Register Reg = MO.getReg(); 777 778 if (RISCV::VRM2RegClass.contains(Reg) || 779 RISCV::VRM4RegClass.contains(Reg) || 780 RISCV::VRM8RegClass.contains(Reg)) { 781 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0); 782 assert(Reg && "Subregister does not exist"); 783 } else if (RISCV::FPR16RegClass.contains(Reg)) { 784 Reg = 785 TRI->getMatchingSuperReg(Reg, RISCV::sub_16, &RISCV::FPR32RegClass); 786 assert(Reg && "Subregister does not exist"); 787 } else if (RISCV::FPR64RegClass.contains(Reg)) { 788 Reg = TRI->getSubReg(Reg, RISCV::sub_32); 789 assert(Reg && "Superregister does not exist"); 790 } else if (RISCV::VRN2M1RegClass.contains(Reg) || 791 RISCV::VRN2M2RegClass.contains(Reg) || 792 RISCV::VRN2M4RegClass.contains(Reg) || 793 RISCV::VRN3M1RegClass.contains(Reg) || 794 RISCV::VRN3M2RegClass.contains(Reg) || 795 RISCV::VRN4M1RegClass.contains(Reg) || 796 RISCV::VRN4M2RegClass.contains(Reg) || 797 RISCV::VRN5M1RegClass.contains(Reg) || 798 RISCV::VRN6M1RegClass.contains(Reg) || 799 RISCV::VRN7M1RegClass.contains(Reg) || 800 RISCV::VRN8M1RegClass.contains(Reg)) { 801 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0); 802 assert(Reg && "Subregister does not exist"); 803 } 804 805 MCOp = MCOperand::createReg(Reg); 806 break; 807 } 808 case MachineOperand::MO_Immediate: 809 MCOp = MCOperand::createImm(MO.getImm()); 810 break; 811 } 812 OutMI.addOperand(MCOp); 813 } 814 815 // Unmasked pseudo instructions need to append dummy mask operand to 816 // V instructions. All V instructions are modeled as the masked version. 817 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode()); 818 if (OutMI.getNumOperands() < OutMCID.getNumOperands()) { 819 assert(OutMCID.operands()[OutMI.getNumOperands()].RegClass == 820 RISCV::VMV0RegClassID && 821 "Expected only mask operand to be missing"); 822 OutMI.addOperand(MCOperand::createReg(RISCV::NoRegister)); 823 } 824 825 assert(OutMI.getNumOperands() == OutMCID.getNumOperands()); 826 return true; 827 } 828 829 bool RISCVAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) { 830 if (lowerRISCVVMachineInstrToMCInst(MI, OutMI)) 831 return false; 832 833 OutMI.setOpcode(MI->getOpcode()); 834 835 for (const MachineOperand &MO : MI->operands()) { 836 MCOperand MCOp; 837 if (lowerOperand(MO, MCOp)) 838 OutMI.addOperand(MCOp); 839 } 840 841 switch (OutMI.getOpcode()) { 842 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: { 843 const Function &F = MI->getParent()->getParent()->getFunction(); 844 if (F.hasFnAttribute("patchable-function-entry")) { 845 unsigned Num; 846 if (F.getFnAttribute("patchable-function-entry") 847 .getValueAsString() 848 .getAsInteger(10, Num)) 849 return false; 850 emitNops(Num); 851 return true; 852 } 853 break; 854 } 855 } 856 return false; 857 } 858