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 &DispImm = 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 (!DispImm.isImm()) 234 return true; 235 236 OS << DispImm.getImm() << "(" 237 << RISCVInstPrinter::getRegisterName(AddrReg.getReg()) << ")"; 238 return false; 239 } 240 241 bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 242 STI = &MF.getSubtarget<RISCVSubtarget>(); 243 244 SetupMachineFunction(MF); 245 emitFunctionBody(); 246 return false; 247 } 248 249 void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) { 250 RISCVTargetStreamer &RTS = 251 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); 252 if (const MDString *ModuleTargetABI = 253 dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi"))) 254 RTS.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI->getString())); 255 if (TM.getTargetTriple().isOSBinFormatELF()) 256 emitAttributes(); 257 } 258 259 void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) { 260 RISCVTargetStreamer &RTS = 261 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); 262 263 if (TM.getTargetTriple().isOSBinFormatELF()) 264 RTS.finishAttributeSection(); 265 EmitHwasanMemaccessSymbols(M); 266 } 267 268 void RISCVAsmPrinter::emitAttributes() { 269 RISCVTargetStreamer &RTS = 270 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); 271 // Use MCSubtargetInfo from TargetMachine. Individual functions may have 272 // attributes that differ from other functions in the module and we have no 273 // way to know which function is correct. 274 RTS.emitTargetAttributes(*TM.getMCSubtargetInfo(), /*EmitStackAlign*/ true); 275 } 276 277 void RISCVAsmPrinter::emitFunctionEntryLabel() { 278 const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>(); 279 if (RMFI->isVectorCall()) { 280 auto &RTS = 281 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); 282 RTS.emitDirectiveVariantCC(*CurrentFnSym); 283 } 284 return AsmPrinter::emitFunctionEntryLabel(); 285 } 286 287 // Force static initialization. 288 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter() { 289 RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target()); 290 RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target()); 291 } 292 293 void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) { 294 Register Reg = MI.getOperand(0).getReg(); 295 uint32_t AccessInfo = MI.getOperand(1).getImm(); 296 MCSymbol *&Sym = 297 HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)]; 298 if (!Sym) { 299 // FIXME: Make this work on non-ELF. 300 if (!TM.getTargetTriple().isOSBinFormatELF()) 301 report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF"); 302 303 std::string SymName = "__hwasan_check_x" + utostr(Reg - RISCV::X0) + "_" + 304 utostr(AccessInfo) + "_short"; 305 Sym = OutContext.getOrCreateSymbol(SymName); 306 } 307 auto Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, OutContext); 308 auto Expr = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, OutContext); 309 310 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr)); 311 } 312 313 void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) { 314 Register AddrReg = MI.getOperand(0).getReg(); 315 assert(std::next(MI.getIterator())->isCall() && 316 "KCFI_CHECK not followed by a call instruction"); 317 assert(std::next(MI.getIterator())->getOperand(0).getReg() == AddrReg && 318 "KCFI_CHECK call target doesn't match call operand"); 319 320 // Temporary registers for comparing the hashes. If a register is used 321 // for the call target, or reserved by the user, we can clobber another 322 // temporary register as the check is immediately followed by the 323 // call. The check defaults to X6/X7, but can fall back to X28-X31 if 324 // needed. 325 unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7}; 326 unsigned NextReg = RISCV::X28; 327 auto isRegAvailable = [&](unsigned Reg) { 328 return Reg != AddrReg && !STI->isRegisterReservedByUser(Reg); 329 }; 330 for (auto &Reg : ScratchRegs) { 331 if (isRegAvailable(Reg)) 332 continue; 333 while (!isRegAvailable(NextReg)) 334 ++NextReg; 335 Reg = NextReg++; 336 if (Reg > RISCV::X31) 337 report_fatal_error("Unable to find scratch registers for KCFI_CHECK"); 338 } 339 340 if (AddrReg == RISCV::X0) { 341 // Checking X0 makes no sense. Instead of emitting a load, zero 342 // ScratchRegs[0]. 343 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI) 344 .addReg(ScratchRegs[0]) 345 .addReg(RISCV::X0) 346 .addImm(0)); 347 } else { 348 // Adjust the offset for patchable-function-prefix. This assumes that 349 // patchable-function-prefix is the same for all functions. 350 int NopSize = STI->hasStdExtCOrZca() ? 2 : 4; 351 int64_t PrefixNops = 0; 352 (void)MI.getMF() 353 ->getFunction() 354 .getFnAttribute("patchable-function-prefix") 355 .getValueAsString() 356 .getAsInteger(10, PrefixNops); 357 358 // Load the target function type hash. 359 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW) 360 .addReg(ScratchRegs[0]) 361 .addReg(AddrReg) 362 .addImm(-(PrefixNops * NopSize + 4))); 363 } 364 365 // Load the expected 32-bit type hash. 366 const int64_t Type = MI.getOperand(1).getImm(); 367 const int64_t Hi20 = ((Type + 0x800) >> 12) & 0xFFFFF; 368 const int64_t Lo12 = SignExtend64<12>(Type); 369 if (Hi20) { 370 EmitToStreamer( 371 *OutStreamer, 372 MCInstBuilder(RISCV::LUI).addReg(ScratchRegs[1]).addImm(Hi20)); 373 } 374 if (Lo12 || Hi20 == 0) { 375 EmitToStreamer(*OutStreamer, 376 MCInstBuilder((STI->hasFeature(RISCV::Feature64Bit) && Hi20) 377 ? RISCV::ADDIW 378 : RISCV::ADDI) 379 .addReg(ScratchRegs[1]) 380 .addReg(ScratchRegs[1]) 381 .addImm(Lo12)); 382 } 383 384 // Compare the hashes and trap if there's a mismatch. 385 MCSymbol *Pass = OutContext.createTempSymbol(); 386 EmitToStreamer(*OutStreamer, 387 MCInstBuilder(RISCV::BEQ) 388 .addReg(ScratchRegs[0]) 389 .addReg(ScratchRegs[1]) 390 .addExpr(MCSymbolRefExpr::create(Pass, OutContext))); 391 392 MCSymbol *Trap = OutContext.createTempSymbol(); 393 OutStreamer->emitLabel(Trap); 394 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::EBREAK)); 395 emitKCFITrapEntry(*MI.getMF(), Trap); 396 OutStreamer->emitLabel(Pass); 397 } 398 399 void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) { 400 if (HwasanMemaccessSymbols.empty()) 401 return; 402 403 assert(TM.getTargetTriple().isOSBinFormatELF()); 404 // Use MCSubtargetInfo from TargetMachine. Individual functions may have 405 // attributes that differ from other functions in the module and we have no 406 // way to know which function is correct. 407 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo(); 408 409 MCSymbol *HwasanTagMismatchV2Sym = 410 OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2"); 411 // Annotate symbol as one having incompatible calling convention, so 412 // run-time linkers can instead eagerly bind this function. 413 auto &RTS = 414 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); 415 RTS.emitDirectiveVariantCC(*HwasanTagMismatchV2Sym); 416 417 const MCSymbolRefExpr *HwasanTagMismatchV2Ref = 418 MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext); 419 auto Expr = RISCVMCExpr::create(HwasanTagMismatchV2Ref, 420 RISCVMCExpr::VK_RISCV_CALL, OutContext); 421 422 for (auto &P : HwasanMemaccessSymbols) { 423 unsigned Reg = std::get<0>(P.first); 424 uint32_t AccessInfo = std::get<1>(P.first); 425 MCSymbol *Sym = P.second; 426 427 unsigned Size = 428 1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf); 429 OutStreamer->switchSection(OutContext.getELFSection( 430 ".text.hot", ELF::SHT_PROGBITS, 431 ELF::SHF_EXECINSTR | ELF::SHF_ALLOC | ELF::SHF_GROUP, 0, Sym->getName(), 432 /*IsComdat=*/true)); 433 434 OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction); 435 OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak); 436 OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden); 437 OutStreamer->emitLabel(Sym); 438 439 // Extract shadow offset from ptr 440 OutStreamer->emitInstruction( 441 MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(Reg).addImm(8), 442 MCSTI); 443 OutStreamer->emitInstruction(MCInstBuilder(RISCV::SRLI) 444 .addReg(RISCV::X6) 445 .addReg(RISCV::X6) 446 .addImm(12), 447 MCSTI); 448 // load shadow tag in X6, X5 contains shadow base 449 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADD) 450 .addReg(RISCV::X6) 451 .addReg(RISCV::X5) 452 .addReg(RISCV::X6), 453 MCSTI); 454 OutStreamer->emitInstruction( 455 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0), 456 MCSTI); 457 // Extract tag from X5 and compare it with loaded tag from shadow 458 OutStreamer->emitInstruction( 459 MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(Reg).addImm(56), 460 MCSTI); 461 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol(); 462 // X7 contains tag from memory, while X6 contains tag from the pointer 463 OutStreamer->emitInstruction( 464 MCInstBuilder(RISCV::BNE) 465 .addReg(RISCV::X7) 466 .addReg(RISCV::X6) 467 .addExpr(MCSymbolRefExpr::create(HandleMismatchOrPartialSym, 468 OutContext)), 469 MCSTI); 470 MCSymbol *ReturnSym = OutContext.createTempSymbol(); 471 OutStreamer->emitLabel(ReturnSym); 472 OutStreamer->emitInstruction(MCInstBuilder(RISCV::JALR) 473 .addReg(RISCV::X0) 474 .addReg(RISCV::X1) 475 .addImm(0), 476 MCSTI); 477 OutStreamer->emitLabel(HandleMismatchOrPartialSym); 478 479 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI) 480 .addReg(RISCV::X28) 481 .addReg(RISCV::X0) 482 .addImm(16), 483 MCSTI); 484 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol(); 485 OutStreamer->emitInstruction( 486 MCInstBuilder(RISCV::BGEU) 487 .addReg(RISCV::X6) 488 .addReg(RISCV::X28) 489 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)), 490 MCSTI); 491 492 OutStreamer->emitInstruction( 493 MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(Reg).addImm(0xF), 494 MCSTI); 495 496 if (Size != 1) 497 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI) 498 .addReg(RISCV::X28) 499 .addReg(RISCV::X28) 500 .addImm(Size - 1), 501 MCSTI); 502 OutStreamer->emitInstruction( 503 MCInstBuilder(RISCV::BGE) 504 .addReg(RISCV::X28) 505 .addReg(RISCV::X6) 506 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)), 507 MCSTI); 508 509 OutStreamer->emitInstruction( 510 MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(Reg).addImm(0xF), 511 MCSTI); 512 OutStreamer->emitInstruction( 513 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0), 514 MCSTI); 515 OutStreamer->emitInstruction( 516 MCInstBuilder(RISCV::BEQ) 517 .addReg(RISCV::X6) 518 .addReg(RISCV::X7) 519 .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)), 520 MCSTI); 521 522 OutStreamer->emitLabel(HandleMismatchSym); 523 524 // | Previous stack frames... | 525 // +=================================+ <-- [SP + 256] 526 // | ... | 527 // | | 528 // | Stack frame space for x12 - x31.| 529 // | | 530 // | ... | 531 // +---------------------------------+ <-- [SP + 96] 532 // | Saved x11(arg1), as | 533 // | __hwasan_check_* clobbers it. | 534 // +---------------------------------+ <-- [SP + 88] 535 // | Saved x10(arg0), as | 536 // | __hwasan_check_* clobbers it. | 537 // +---------------------------------+ <-- [SP + 80] 538 // | | 539 // | Stack frame space for x9. | 540 // +---------------------------------+ <-- [SP + 72] 541 // | | 542 // | Saved x8(fp), as | 543 // | __hwasan_check_* clobbers it. | 544 // +---------------------------------+ <-- [SP + 64] 545 // | ... | 546 // | | 547 // | Stack frame space for x2 - x7. | 548 // | | 549 // | ... | 550 // +---------------------------------+ <-- [SP + 16] 551 // | Return address (x1) for caller | 552 // | of __hwasan_check_*. | 553 // +---------------------------------+ <-- [SP + 8] 554 // | Reserved place for x0, possibly | 555 // | junk, since we don't save it. | 556 // +---------------------------------+ <-- [x2 / SP] 557 558 // Adjust sp 559 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI) 560 .addReg(RISCV::X2) 561 .addReg(RISCV::X2) 562 .addImm(-256), 563 MCSTI); 564 565 // store x10(arg0) by new sp 566 OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD) 567 .addReg(RISCV::X10) 568 .addReg(RISCV::X2) 569 .addImm(8 * 10), 570 MCSTI); 571 // store x11(arg1) by new sp 572 OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD) 573 .addReg(RISCV::X11) 574 .addReg(RISCV::X2) 575 .addImm(8 * 11), 576 MCSTI); 577 578 // store x8(fp) by new sp 579 OutStreamer->emitInstruction( 580 MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 * 581 8), 582 MCSTI); 583 // store x1(ra) by new sp 584 OutStreamer->emitInstruction( 585 MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 * 586 8), 587 MCSTI); 588 if (Reg != RISCV::X10) 589 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI) 590 .addReg(RISCV::X10) 591 .addReg(Reg) 592 .addImm(0), 593 MCSTI); 594 OutStreamer->emitInstruction( 595 MCInstBuilder(RISCV::ADDI) 596 .addReg(RISCV::X11) 597 .addReg(RISCV::X0) 598 .addImm(AccessInfo & HWASanAccessInfo::RuntimeMask), 599 MCSTI); 600 601 OutStreamer->emitInstruction(MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr), 602 MCSTI); 603 } 604 } 605 606 static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, 607 const AsmPrinter &AP) { 608 MCContext &Ctx = AP.OutContext; 609 RISCVMCExpr::VariantKind Kind; 610 611 switch (MO.getTargetFlags()) { 612 default: 613 llvm_unreachable("Unknown target flag on GV operand"); 614 case RISCVII::MO_None: 615 Kind = RISCVMCExpr::VK_RISCV_None; 616 break; 617 case RISCVII::MO_CALL: 618 Kind = RISCVMCExpr::VK_RISCV_CALL; 619 break; 620 case RISCVII::MO_PLT: 621 Kind = RISCVMCExpr::VK_RISCV_CALL_PLT; 622 break; 623 case RISCVII::MO_LO: 624 Kind = RISCVMCExpr::VK_RISCV_LO; 625 break; 626 case RISCVII::MO_HI: 627 Kind = RISCVMCExpr::VK_RISCV_HI; 628 break; 629 case RISCVII::MO_PCREL_LO: 630 Kind = RISCVMCExpr::VK_RISCV_PCREL_LO; 631 break; 632 case RISCVII::MO_PCREL_HI: 633 Kind = RISCVMCExpr::VK_RISCV_PCREL_HI; 634 break; 635 case RISCVII::MO_GOT_HI: 636 Kind = RISCVMCExpr::VK_RISCV_GOT_HI; 637 break; 638 case RISCVII::MO_TPREL_LO: 639 Kind = RISCVMCExpr::VK_RISCV_TPREL_LO; 640 break; 641 case RISCVII::MO_TPREL_HI: 642 Kind = RISCVMCExpr::VK_RISCV_TPREL_HI; 643 break; 644 case RISCVII::MO_TPREL_ADD: 645 Kind = RISCVMCExpr::VK_RISCV_TPREL_ADD; 646 break; 647 case RISCVII::MO_TLS_GOT_HI: 648 Kind = RISCVMCExpr::VK_RISCV_TLS_GOT_HI; 649 break; 650 case RISCVII::MO_TLS_GD_HI: 651 Kind = RISCVMCExpr::VK_RISCV_TLS_GD_HI; 652 break; 653 } 654 655 const MCExpr *ME = 656 MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, Ctx); 657 658 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset()) 659 ME = MCBinaryExpr::createAdd( 660 ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx); 661 662 if (Kind != RISCVMCExpr::VK_RISCV_None) 663 ME = RISCVMCExpr::create(ME, Kind, Ctx); 664 return MCOperand::createExpr(ME); 665 } 666 667 bool RISCVAsmPrinter::lowerOperand(const MachineOperand &MO, 668 MCOperand &MCOp) const { 669 switch (MO.getType()) { 670 default: 671 report_fatal_error("lowerOperand: unknown operand type"); 672 case MachineOperand::MO_Register: 673 // Ignore all implicit register operands. 674 if (MO.isImplicit()) 675 return false; 676 MCOp = MCOperand::createReg(MO.getReg()); 677 break; 678 case MachineOperand::MO_RegisterMask: 679 // Regmasks are like implicit defs. 680 return false; 681 case MachineOperand::MO_Immediate: 682 MCOp = MCOperand::createImm(MO.getImm()); 683 break; 684 case MachineOperand::MO_MachineBasicBlock: 685 MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), *this); 686 break; 687 case MachineOperand::MO_GlobalAddress: 688 MCOp = lowerSymbolOperand(MO, getSymbolPreferLocal(*MO.getGlobal()), *this); 689 break; 690 case MachineOperand::MO_BlockAddress: 691 MCOp = lowerSymbolOperand(MO, GetBlockAddressSymbol(MO.getBlockAddress()), 692 *this); 693 break; 694 case MachineOperand::MO_ExternalSymbol: 695 MCOp = lowerSymbolOperand(MO, GetExternalSymbolSymbol(MO.getSymbolName()), 696 *this); 697 break; 698 case MachineOperand::MO_ConstantPoolIndex: 699 MCOp = lowerSymbolOperand(MO, GetCPISymbol(MO.getIndex()), *this); 700 break; 701 case MachineOperand::MO_JumpTableIndex: 702 MCOp = lowerSymbolOperand(MO, GetJTISymbol(MO.getIndex()), *this); 703 break; 704 case MachineOperand::MO_MCSymbol: 705 MCOp = lowerSymbolOperand(MO, MO.getMCSymbol(), *this); 706 break; 707 } 708 return true; 709 } 710 711 static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI, 712 MCInst &OutMI) { 713 const RISCVVPseudosTable::PseudoInfo *RVV = 714 RISCVVPseudosTable::getPseudoInfo(MI->getOpcode()); 715 if (!RVV) 716 return false; 717 718 OutMI.setOpcode(RVV->BaseInstr); 719 720 const MachineBasicBlock *MBB = MI->getParent(); 721 assert(MBB && "MI expected to be in a basic block"); 722 const MachineFunction *MF = MBB->getParent(); 723 assert(MF && "MBB expected to be in a machine function"); 724 725 const RISCVSubtarget &Subtarget = MF->getSubtarget<RISCVSubtarget>(); 726 const TargetInstrInfo *TII = Subtarget.getInstrInfo(); 727 const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); 728 assert(TRI && "TargetRegisterInfo expected"); 729 730 const MCInstrDesc &MCID = MI->getDesc(); 731 uint64_t TSFlags = MCID.TSFlags; 732 unsigned NumOps = MI->getNumExplicitOperands(); 733 734 // Skip policy, VL and SEW operands which are the last operands if present. 735 if (RISCVII::hasVecPolicyOp(TSFlags)) 736 --NumOps; 737 if (RISCVII::hasVLOp(TSFlags)) 738 --NumOps; 739 if (RISCVII::hasSEWOp(TSFlags)) 740 --NumOps; 741 if (RISCVII::hasRoundModeOp(TSFlags)) 742 --NumOps; 743 744 bool hasVLOutput = RISCV::isFaultFirstLoad(*MI); 745 for (unsigned OpNo = 0; OpNo != NumOps; ++OpNo) { 746 const MachineOperand &MO = MI->getOperand(OpNo); 747 // Skip vl ouput. It should be the second output. 748 if (hasVLOutput && OpNo == 1) 749 continue; 750 751 // Skip merge op. It should be the first operand after the defs. 752 if (OpNo == MI->getNumExplicitDefs() && MO.isReg() && MO.isTied()) { 753 assert(MCID.getOperandConstraint(OpNo, MCOI::TIED_TO) == 0 && 754 "Expected tied to first def."); 755 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode()); 756 // Skip if the next operand in OutMI is not supposed to be tied. Unless it 757 // is a _TIED instruction. 758 if (OutMCID.getOperandConstraint(OutMI.getNumOperands(), MCOI::TIED_TO) < 759 0 && 760 !RISCVII::isTiedPseudo(TSFlags)) 761 continue; 762 } 763 764 MCOperand MCOp; 765 switch (MO.getType()) { 766 default: 767 llvm_unreachable("Unknown operand type"); 768 case MachineOperand::MO_Register: { 769 Register Reg = MO.getReg(); 770 771 if (RISCV::VRM2RegClass.contains(Reg) || 772 RISCV::VRM4RegClass.contains(Reg) || 773 RISCV::VRM8RegClass.contains(Reg)) { 774 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0); 775 assert(Reg && "Subregister does not exist"); 776 } else if (RISCV::FPR16RegClass.contains(Reg)) { 777 Reg = 778 TRI->getMatchingSuperReg(Reg, RISCV::sub_16, &RISCV::FPR32RegClass); 779 assert(Reg && "Subregister does not exist"); 780 } else if (RISCV::FPR64RegClass.contains(Reg)) { 781 Reg = TRI->getSubReg(Reg, RISCV::sub_32); 782 assert(Reg && "Superregister does not exist"); 783 } else if (RISCV::VRN2M1RegClass.contains(Reg) || 784 RISCV::VRN2M2RegClass.contains(Reg) || 785 RISCV::VRN2M4RegClass.contains(Reg) || 786 RISCV::VRN3M1RegClass.contains(Reg) || 787 RISCV::VRN3M2RegClass.contains(Reg) || 788 RISCV::VRN4M1RegClass.contains(Reg) || 789 RISCV::VRN4M2RegClass.contains(Reg) || 790 RISCV::VRN5M1RegClass.contains(Reg) || 791 RISCV::VRN6M1RegClass.contains(Reg) || 792 RISCV::VRN7M1RegClass.contains(Reg) || 793 RISCV::VRN8M1RegClass.contains(Reg)) { 794 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0); 795 assert(Reg && "Subregister does not exist"); 796 } 797 798 MCOp = MCOperand::createReg(Reg); 799 break; 800 } 801 case MachineOperand::MO_Immediate: 802 MCOp = MCOperand::createImm(MO.getImm()); 803 break; 804 } 805 OutMI.addOperand(MCOp); 806 } 807 808 // Unmasked pseudo instructions need to append dummy mask operand to 809 // V instructions. All V instructions are modeled as the masked version. 810 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode()); 811 if (OutMI.getNumOperands() < OutMCID.getNumOperands()) { 812 assert(OutMCID.operands()[OutMI.getNumOperands()].RegClass == 813 RISCV::VMV0RegClassID && 814 "Expected only mask operand to be missing"); 815 OutMI.addOperand(MCOperand::createReg(RISCV::NoRegister)); 816 } 817 818 assert(OutMI.getNumOperands() == OutMCID.getNumOperands()); 819 return true; 820 } 821 822 bool RISCVAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) { 823 if (lowerRISCVVMachineInstrToMCInst(MI, OutMI)) 824 return false; 825 826 OutMI.setOpcode(MI->getOpcode()); 827 828 for (const MachineOperand &MO : MI->operands()) { 829 MCOperand MCOp; 830 if (lowerOperand(MO, MCOp)) 831 OutMI.addOperand(MCOp); 832 } 833 834 switch (OutMI.getOpcode()) { 835 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: { 836 const Function &F = MI->getParent()->getParent()->getFunction(); 837 if (F.hasFnAttribute("patchable-function-entry")) { 838 unsigned Num; 839 if (F.getFnAttribute("patchable-function-entry") 840 .getValueAsString() 841 .getAsInteger(10, Num)) 842 return false; 843 emitNops(Num); 844 return true; 845 } 846 break; 847 } 848 } 849 return false; 850 } 851