LLVM: lib/Target/RISCV/RISCVAsmPrinter.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

45

46using namespace llvm;

47

48#define DEBUG_TYPE "asm-printer"

49

51 "Number of RISC-V Compressed instructions emitted");

52

53namespace llvm {

55}

56

57namespace {

58class RISCVAsmPrinter : public AsmPrinter {

59public:

60 static char ID;

61

62private:

63 const RISCVSubtarget *STI;

64

65public:

66 explicit RISCVAsmPrinter(TargetMachine &TM,

67 std::unique_ptr Streamer)

68 : AsmPrinter(TM, std::move(Streamer), ID) {}

69

70 StringRef getPassName() const override { return "RISC-V Assembly Printer"; }

71

72 void LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,

73 const MachineInstr &MI);

74

75 void LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,

76 const MachineInstr &MI);

77

78 void LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,

79 const MachineInstr &MI);

80

81 bool runOnMachineFunction(MachineFunction &MF) override;

82

84

85 void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override;

86

87 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,

88 const char *ExtraCode, raw_ostream &OS) override;

89 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,

90 const char *ExtraCode, raw_ostream &OS) override;

91

92

93 bool EmitToStreamer(MCStreamer &S, const MCInst &Inst,

94 const MCSubtargetInfo &SubtargetInfo);

95 bool EmitToStreamer(MCStreamer &S, const MCInst &Inst) {

96 return EmitToStreamer(S, Inst, *STI);

97 }

98

99 bool lowerPseudoInstExpansion(const MachineInstr *MI, MCInst &Inst);

100

101 typedef std::tuple<unsigned, uint32_t> HwasanMemaccessTuple;

102 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols;

103 void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI);

104 void LowerKCFI_CHECK(const MachineInstr &MI);

105 void EmitHwasanMemaccessSymbols(Module &M);

106

107

108 bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const;

109

110 void emitStartOfAsmFile(Module &M) override;

111 void emitEndOfAsmFile(Module &M) override;

112

113 void emitFunctionEntryLabel() override;

114 bool emitDirectiveOptionArch();

115

116 void emitNoteGnuProperty(const Module &M);

117

118private:

119 void emitAttributes(const MCSubtargetInfo &SubtargetInfo);

120

121 void emitNTLHint(const MachineInstr *MI);

122

123

124 void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr *MI);

125 void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr *MI);

126 void LowerPATCHABLE_TAIL_CALL(const MachineInstr *MI);

127 void emitSled(const MachineInstr *MI, SledKind Kind);

128

129 void lowerToMCInst(const MachineInstr *MI, MCInst &OutMI);

130};

131}

132

133void RISCVAsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,

135 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;

136 unsigned NumNOPBytes = StackMapOpers(&MI).getNumPatchBytes();

137

138 auto &Ctx = OutStreamer.getContext();

139 MCSymbol *MILabel = Ctx.createTempSymbol();

141

143 assert(NumNOPBytes % NOPBytes == 0 &&

144 "Invalid number of NOP bytes requested!");

145

146

147 const MachineBasicBlock &MBB = *MI.getParent();

149 ++MII;

150 while (NumNOPBytes > 0) {

151 if (MII == MBB.end() || MII->isCall() ||

152 MII->getOpcode() == RISCV::DBG_VALUE ||

153 MII->getOpcode() == TargetOpcode::PATCHPOINT ||

154 MII->getOpcode() == TargetOpcode::STACKMAP)

155 break;

156 ++MII;

157 NumNOPBytes -= 4;

158 }

159

160

161 emitNops(NumNOPBytes / NOPBytes);

162}

163

164

165

166void RISCVAsmPrinter::LowerPATCHPOINT(MCStreamer &OutStreamer, StackMaps &SM,

167 const MachineInstr &MI) {

168 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;

169

170 auto &Ctx = OutStreamer.getContext();

171 MCSymbol *MILabel = Ctx.createTempSymbol();

174

175 PatchPointOpers Opers(&MI);

176

177 const MachineOperand &CalleeMO = Opers.getCallTarget();

178 unsigned EncodedBytes = 0;

179

180 if (CalleeMO.isImm()) {

181 uint64_t CallTarget = CalleeMO.getImm();

182 if (CallTarget) {

183 assert((CallTarget & 0xFFFF'FFFF'FFFF) == CallTarget &&

184 "High 16 bits of call target should be zero.");

185

188 for (MCInst &Inst : Seq) {

189 bool Compressed = EmitToStreamer(OutStreamer, Inst);

190 EncodedBytes += Compressed ? 2 : 4;

191 }

192 bool Compressed = EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)

193 .addReg(RISCV::X1)

194 .addReg(RISCV::X1)

195 .addImm(0));

196 EncodedBytes += Compressed ? 2 : 4;

197 }

198 } else if (CalleeMO.isGlobal()) {

199 MCOperand CallTargetMCOp;

200 lowerOperand(CalleeMO, CallTargetMCOp);

201 EmitToStreamer(OutStreamer,

202 MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp));

203 EncodedBytes += 8;

204 }

205

206

207 unsigned NumBytes = Opers.getNumPatchBytes();

208 assert(NumBytes >= EncodedBytes &&

209 "Patchpoint can't request size less than the length of a call.");

210 assert((NumBytes - EncodedBytes) % NOPBytes == 0 &&

211 "Invalid number of NOP bytes requested!");

212 emitNops((NumBytes - EncodedBytes) / NOPBytes);

213}

214

215void RISCVAsmPrinter::LowerSTATEPOINT(MCStreamer &OutStreamer, StackMaps &SM,

216 const MachineInstr &MI) {

217 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;

218

219 StatepointOpers SOpers(&MI);

220 if (unsigned PatchBytes = SOpers.getNumPatchBytes()) {

221 assert(PatchBytes % NOPBytes == 0 &&

222 "Invalid number of NOP bytes requested!");

223 emitNops(PatchBytes / NOPBytes);

224 } else {

225

226 const MachineOperand &CallTarget = SOpers.getCallTarget();

227 MCOperand CallTargetMCOp;

228 switch (CallTarget.getType()) {

231 lowerOperand(CallTarget, CallTargetMCOp);

232 EmitToStreamer(

233 OutStreamer,

234 MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp));

235 break;

238 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JAL)

239 .addReg(RISCV::X1)

241 break;

244 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)

245 .addReg(RISCV::X1)

247 .addImm(0));

248 break;

249 default:

250 llvm_unreachable("Unsupported operand type in statepoint call target");

251 break;

252 }

253 }

254

255 auto &Ctx = OutStreamer.getContext();

256 MCSymbol *MILabel = Ctx.createTempSymbol();

259}

260

261bool RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst,

262 const MCSubtargetInfo &SubtargetInfo) {

263 MCInst CInst;

265 if (Res)

266 ++RISCVNumInstrsCompressed;

268 return Res;

269}

270

271

272

273#include "RISCVGenMCPseudoLowering.inc"

274

275

276

277void RISCVAsmPrinter::emitNTLHint(const MachineInstr *MI) {

278 if (!STI->hasStdExtZihintntl())

279 return;

280

281 if (MI->memoperands_empty())

282 return;

283

284 MachineMemOperand *MMO = *(MI->memoperands_begin());

286 return;

287

288 unsigned NontemporalMode = 0;

290 NontemporalMode += 0b1;

292 NontemporalMode += 0b10;

293

295 if (STI->hasStdExtZca())

296 Hint.setOpcode(RISCV::C_ADD);

297 else

298 Hint.setOpcode(RISCV::ADD);

299

303

304 EmitToStreamer(*OutStreamer, Hint);

305}

306

307void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) {

308 RISCV_MC::verifyInstructionPredicates(MI->getOpcode(), STI->getFeatureBits());

309

310 emitNTLHint(MI);

311

312

313 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {

314 EmitToStreamer(*OutStreamer, OutInst);

315 return;

316 }

317

318 switch (MI->getOpcode()) {

319 case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES:

320 LowerHWASAN_CHECK_MEMACCESS(*MI);

321 return;

322 case RISCV::KCFI_CHECK:

323 LowerKCFI_CHECK(*MI);

324 return;

325 case TargetOpcode::STACKMAP:

326 return LowerSTACKMAP(*OutStreamer, SM, *MI);

327 case TargetOpcode::PATCHPOINT:

328 return LowerPATCHPOINT(*OutStreamer, SM, *MI);

329 case TargetOpcode::STATEPOINT:

330 return LowerSTATEPOINT(*OutStreamer, SM, *MI);

331 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {

332 const Function &F = MI->getParent()->getParent()->getFunction();

333 if (F.hasFnAttribute("patchable-function-entry")) {

334 unsigned Num;

335 [[maybe_unused]] bool Result =

336 F.getFnAttribute("patchable-function-entry")

337 .getValueAsString()

338 .getAsInteger(10, Num);

339 assert(!Result && "Enforced by the verifier");

340 emitNops(Num);

341 return;

342 }

343 LowerPATCHABLE_FUNCTION_ENTER(MI);

344 return;

345 }

346 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:

347 LowerPATCHABLE_FUNCTION_EXIT(MI);

348 return;

349 case TargetOpcode::PATCHABLE_TAIL_CALL:

350 LowerPATCHABLE_TAIL_CALL(MI);

351 return;

352 }

353

354 MCInst OutInst;

355 lowerToMCInst(MI, OutInst);

356 EmitToStreamer(*OutStreamer, OutInst);

357}

358

359bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,

360 const char *ExtraCode, raw_ostream &OS) {

361

363 return false;

364

365 const MachineOperand &MO = MI->getOperand(OpNo);

366 if (ExtraCode && ExtraCode[0]) {

367 if (ExtraCode[1] != 0)

368 return true;

369

370 switch (ExtraCode[0]) {

371 default:

372 return true;

373 case 'z':

376 return false;

377 }

378 break;

379 case 'i':

381 OS << 'i';

382 return false;

383 case 'N':

385 return true;

386

388 OS << TRI->getEncodingValue(MO.getReg());

389 return false;

390 }

391 }

392

396 return false;

399 return false;

401 PrintSymbolOperand(MO, OS);

402 return false;

405 Sym->print(OS, MAI);

406 return false;

407 }

408 default:

409 break;

410 }

411

412 return true;

413}

414

415bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,

416 unsigned OpNo,

417 const char *ExtraCode,

418 raw_ostream &OS) {

419 if (ExtraCode)

421

422 const MachineOperand &AddrReg = MI->getOperand(OpNo);

423 assert(MI->getNumOperands() > OpNo + 1 && "Expected additional operand");

424 const MachineOperand &Offset = MI->getOperand(OpNo + 1);

425

426

427 if (!AddrReg.isReg())

428 return true;

429 if (Offset.isImm() && Offset.isGlobal() && Offset.isBlockAddress() &&

430 Offset.isMCSymbol())

431 return true;

432

433 MCOperand MCO;

434 if (!lowerOperand(Offset, MCO))

435 return true;

436

439 else if (Offset.isGlobal() || Offset.isBlockAddress() || Offset.isMCSymbol())

440 MAI->printExpr(OS, *MCO.getExpr());

441

442 if (Offset.isMCSymbol())

443 MMI->getContext().registerInlineAsmLabel(Offset.getMCSymbol());

444 if (Offset.isBlockAddress()) {

446 MCSymbol *Sym = GetBlockAddressSymbol(BA);

447 MMI->getContext().registerInlineAsmLabel(Sym);

448 }

449

451 return false;

452}

453

454bool RISCVAsmPrinter::emitDirectiveOptionArch() {

455 RISCVTargetStreamer &RTS =

456 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());

458 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();

460 if (STI->hasFeature(Feature.Value) == MCSTI.hasFeature(Feature.Value))

461 continue;

462

464 continue;

465

466 auto Delta = STI->hasFeature(Feature.Value) ? RISCVOptionArchArgType::Plus

467 : RISCVOptionArchArgType::Minus;

468 NeedEmitStdOptionArgs.emplace_back(Delta, Feature.Key);

469 }

470 if (!NeedEmitStdOptionArgs.empty()) {

473 return true;

474 }

475

476 return false;

477}

478

479bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {

481 RISCVTargetStreamer &RTS =

482 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());

483

484 bool EmittedOptionArch = emitDirectiveOptionArch();

485

486 SetupMachineFunction(MF);

487 emitFunctionBody();

488

489

490 emitXRayTable();

491

492 if (EmittedOptionArch)

493 RTS.emitDirectiveOptionPop();

494 return false;

495}

496

497void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr *MI) {

498 emitSled(MI, SledKind::FUNCTION_ENTER);

499}

500

501void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr *MI) {

502 emitSled(MI, SledKind::FUNCTION_EXIT);

503}

504

505void RISCVAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr *MI) {

506 emitSled(MI, SledKind::TAIL_CALL);

507}

508

509void RISCVAsmPrinter::emitSled(const MachineInstr *MI, SledKind Kind) {

510

511

512

513

514

515

516

517

518

519

520

521

522

523

524 const uint8_t NoopsInSledCount = STI->is64Bit() ? 33 : 21;

525

527 auto CurSled = OutContext.createTempSymbol("xray_sled_", true);

529 auto Target = OutContext.createTempSymbol();

530

532

533

534

535 EmitToStreamer(

536 *OutStreamer,

537 MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addExpr(TargetExpr));

538

539

540 for (int8_t I = 0; I < NoopsInSledCount; ++I)

541 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)

542 .addReg(RISCV::X0)

543 .addReg(RISCV::X0)

544 .addImm(0));

545

547 recordSled(CurSled, *MI, Kind, 2);

548}

549

550void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) {

551 RISCVTargetStreamer &RTS =

552 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());

553 if (const MDString *ModuleTargetABI =

556

557 MCSubtargetInfo SubtargetInfo = *TM.getMCSubtargetInfo();

558

559

561 for (auto &ISA : MD->operands()) {

564 ISAString->getString(), true,

565 true);

566 if (errorToBool(ParseResult.takeError())) {

567 auto &ISAInfo = *ParseResult;

569 if (ISAInfo->hasExtension(Feature.Key) &&

570 !SubtargetInfo.hasFeature(Feature.Value))

572 }

573 }

574 }

575 }

576

578 }

579

580 if (TM.getTargetTriple().isOSBinFormatELF())

581 emitAttributes(SubtargetInfo);

582}

583

584void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {

585 RISCVTargetStreamer &RTS =

586 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());

587

588 if (TM.getTargetTriple().isOSBinFormatELF()) {

590 emitNoteGnuProperty(M);

591 }

592 EmitHwasanMemaccessSymbols(M);

593}

594

595void RISCVAsmPrinter::emitAttributes(const MCSubtargetInfo &SubtargetInfo) {

596 RISCVTargetStreamer &RTS =

597 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());

598

599

600

602}

603

604void RISCVAsmPrinter::emitFunctionEntryLabel() {

605 const auto *RMFI = MF->getInfo();

606 if (RMFI->isVectorCall()) {

607 auto &RTS =

608 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());

610 }

612}

613

614

622

623void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {

625 uint32_t AccessInfo = MI.getOperand(1).getImm();

627 HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)];

628 if (!Sym) {

629

630 if (!TM.getTargetTriple().isOSBinFormatELF())

631 report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");

632

633 std::string SymName = "__hwasan_check_x" + utostr(Reg - RISCV::X0) + "_" +

634 utostr(AccessInfo) + "_short";

635 Sym = OutContext.getOrCreateSymbol(SymName);

636 }

639

640 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));

641}

642

643void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {

644 Register AddrReg = MI.getOperand(0).getReg();

645 assert(std::next(MI.getIterator())->isCall() &&

646 "KCFI_CHECK not followed by a call instruction");

647 assert(std::next(MI.getIterator())->getOperand(0).getReg() == AddrReg &&

648 "KCFI_CHECK call target doesn't match call operand");

649

650

651

652

653

654

655 unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7};

656 unsigned NextReg = RISCV::X28;

657 auto isRegAvailable = [&](unsigned Reg) {

659 };

660 for (auto &Reg : ScratchRegs) {

661 if (isRegAvailable(Reg))

662 continue;

663 while (!isRegAvailable(NextReg))

664 ++NextReg;

665 Reg = NextReg++;

666 if (Reg > RISCV::X31)

667 report_fatal_error("Unable to find scratch registers for KCFI_CHECK");

668 }

669

670 if (AddrReg == RISCV::X0) {

671

672

673 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)

674 .addReg(ScratchRegs[0])

675 .addReg(RISCV::X0)

676 .addImm(0));

677 } else {

678

679

680 int NopSize = STI->hasStdExtZca() ? 2 : 4;

681 int64_t PrefixNops = 0;

682 (void)MI.getMF()

683 ->getFunction()

684 .getFnAttribute("patchable-function-prefix")

685 .getValueAsString()

686 .getAsInteger(10, PrefixNops);

687

688

689 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW)

690 .addReg(ScratchRegs[0])

691 .addReg(AddrReg)

692 .addImm(-(PrefixNops * NopSize + 4)));

693 }

694

695

696 const int64_t Type = MI.getOperand(1).getImm();

697 const int64_t Hi20 = ((Type + 0x800) >> 12) & 0xFFFFF;

699 if (Hi20) {

700 EmitToStreamer(

701 *OutStreamer,

702 MCInstBuilder(RISCV::LUI).addReg(ScratchRegs[1]).addImm(Hi20));

703 }

704 if (Lo12 || Hi20 == 0) {

705 EmitToStreamer(*OutStreamer,

706 MCInstBuilder((STI->hasFeature(RISCV::Feature64Bit) && Hi20)

707 ? RISCV::ADDIW

708 : RISCV::ADDI)

709 .addReg(ScratchRegs[1])

710 .addReg(ScratchRegs[1])

711 .addImm(Lo12));

712 }

713

714

715 MCSymbol *Pass = OutContext.createTempSymbol();

716 EmitToStreamer(*OutStreamer,

717 MCInstBuilder(RISCV::BEQ)

718 .addReg(ScratchRegs[0])

719 .addReg(ScratchRegs[1])

721

722 MCSymbol *Trap = OutContext.createTempSymbol();

724 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::EBREAK));

725 emitKCFITrapEntry(*MI.getMF(), Trap);

727}

728

729void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {

730 if (HwasanMemaccessSymbols.empty())

731 return;

732

733 assert(TM.getTargetTriple().isOSBinFormatELF());

734

735

736

737 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();

738

739 MCSymbol *HwasanTagMismatchV2Sym =

740 OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2");

741

742

743 auto &RTS =

744 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());

746

747 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =

750 ELF::R_RISCV_CALL_PLT, OutContext);

751

752 for (auto &P : HwasanMemaccessSymbols) {

753 unsigned Reg = std::get<0>(P.first);

754 uint32_t AccessInfo = std::get<1>(P.first);

756

757 unsigned Size =

759 OutStreamer->switchSection(OutContext.getELFSection(

762 true));

763

768

769

770 EmitToStreamer(

771 *OutStreamer,

772 MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(Reg).addImm(8),

773 MCSTI);

774 EmitToStreamer(*OutStreamer,

775 MCInstBuilder(RISCV::SRLI)

776 .addReg(RISCV::X6)

777 .addReg(RISCV::X6)

778 .addImm(12),

779 MCSTI);

780

781 EmitToStreamer(*OutStreamer,

782 MCInstBuilder(RISCV::ADD)

783 .addReg(RISCV::X6)

784 .addReg(RISCV::X5)

785 .addReg(RISCV::X6),

786 MCSTI);

787 EmitToStreamer(

788 *OutStreamer,

789 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),

790 MCSTI);

791

792 EmitToStreamer(

793 *OutStreamer,

794 MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(Reg).addImm(56),

795 MCSTI);

796 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();

797

798 EmitToStreamer(*OutStreamer,

799 MCInstBuilder(RISCV::BNE)

800 .addReg(RISCV::X7)

801 .addReg(RISCV::X6)

803 HandleMismatchOrPartialSym, OutContext)),

804 MCSTI);

805 MCSymbol *ReturnSym = OutContext.createTempSymbol();

806 OutStreamer->emitLabel(ReturnSym);

807 EmitToStreamer(*OutStreamer,

808 MCInstBuilder(RISCV::JALR)

809 .addReg(RISCV::X0)

810 .addReg(RISCV::X1)

811 .addImm(0),

812 MCSTI);

813 OutStreamer->emitLabel(HandleMismatchOrPartialSym);

814

815 EmitToStreamer(*OutStreamer,

816 MCInstBuilder(RISCV::ADDI)

817 .addReg(RISCV::X28)

818 .addReg(RISCV::X0)

819 .addImm(16),

820 MCSTI);

821 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();

822 EmitToStreamer(

823 *OutStreamer,

824 MCInstBuilder(RISCV::BGEU)

825 .addReg(RISCV::X6)

826 .addReg(RISCV::X28)

828 MCSTI);

829

830 EmitToStreamer(

831 *OutStreamer,

832 MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(Reg).addImm(0xF),

833 MCSTI);

834

835 if (Size != 1)

836 EmitToStreamer(*OutStreamer,

837 MCInstBuilder(RISCV::ADDI)

838 .addReg(RISCV::X28)

839 .addReg(RISCV::X28)

840 .addImm(Size - 1),

841 MCSTI);

842 EmitToStreamer(

843 *OutStreamer,

844 MCInstBuilder(RISCV::BGE)

845 .addReg(RISCV::X28)

846 .addReg(RISCV::X6)

848 MCSTI);

849

850 EmitToStreamer(

851 *OutStreamer,

852 MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(Reg).addImm(0xF),

853 MCSTI);

854 EmitToStreamer(

855 *OutStreamer,

856 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),

857 MCSTI);

858 EmitToStreamer(*OutStreamer,

859 MCInstBuilder(RISCV::BEQ)

860 .addReg(RISCV::X6)

861 .addReg(RISCV::X7)

863 MCSTI);

864

865 OutStreamer->emitLabel(HandleMismatchSym);

866

867

868

869

870

871

872

873

874

875

876

877

878

879

880

881

882

883

884

885

886

887

888

889

890

891

892

893

894

895

896

897

898

899

900

901

902 EmitToStreamer(*OutStreamer,

903 MCInstBuilder(RISCV::ADDI)

904 .addReg(RISCV::X2)

905 .addReg(RISCV::X2)

906 .addImm(-256),

907 MCSTI);

908

909

910 EmitToStreamer(*OutStreamer,

911 MCInstBuilder(RISCV::SD)

912 .addReg(RISCV::X10)

913 .addReg(RISCV::X2)

914 .addImm(8 * 10),

915 MCSTI);

916

917 EmitToStreamer(*OutStreamer,

918 MCInstBuilder(RISCV::SD)

919 .addReg(RISCV::X11)

920 .addReg(RISCV::X2)

921 .addImm(8 * 11),

922 MCSTI);

923

924

925 EmitToStreamer(

926 *OutStreamer,

927 MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 *

928 8),

929 MCSTI);

930

931 EmitToStreamer(

932 *OutStreamer,

933 MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 *

934 8),

935 MCSTI);

936 if (Reg != RISCV::X10)

937 EmitToStreamer(

938 *OutStreamer,

939 MCInstBuilder(RISCV::ADDI).addReg(RISCV::X10).addReg(Reg).addImm(0),

940 MCSTI);

941 EmitToStreamer(*OutStreamer,

942 MCInstBuilder(RISCV::ADDI)

943 .addReg(RISCV::X11)

944 .addReg(RISCV::X0)

946 MCSTI);

947

948 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr),

949 MCSTI);

950 }

951}

952

953void RISCVAsmPrinter::emitNoteGnuProperty(const Module &M) {

954 if (const Metadata *const Flag = M.getModuleFlag("cf-protection-return");

956 RISCVTargetStreamer &RTS =

957 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());

959 }

960}

961

966

968 default:

972 break;

974 Kind = ELF::R_RISCV_CALL_PLT;

975 break;

978 break;

980 Kind = ELF::R_RISCV_HI20;

981 break;

984 break;

986 Kind = ELF::R_RISCV_PCREL_HI20;

987 break;

989 Kind = ELF::R_RISCV_GOT_HI20;

990 break;

993 break;

995 Kind = ELF::R_RISCV_TPREL_HI20;

996 break;

998 Kind = ELF::R_RISCV_TPREL_ADD;

999 break;

1001 Kind = ELF::R_RISCV_TLS_GOT_HI20;

1002 break;

1004 Kind = ELF::R_RISCV_TLS_GD_HI20;

1005 break;

1007 Kind = ELF::R_RISCV_TLSDESC_HI20;

1008 break;

1010 Kind = ELF::R_RISCV_TLSDESC_LOAD_LO12;

1011 break;

1013 Kind = ELF::R_RISCV_TLSDESC_ADD_LO12;

1014 break;

1016 Kind = ELF::R_RISCV_TLSDESC_CALL;

1017 break;

1018 }

1019

1021

1025

1029}

1030

1031bool RISCVAsmPrinter::lowerOperand(const MachineOperand &MO,

1032 MCOperand &MCOp) const {

1034 default:

1037

1039 return false;

1041 break;

1043

1044 return false;

1047 break;

1050 break;

1053 break;

1056 *this);

1057 break;

1060 *this);

1061 break;

1064 break;

1067 break;

1070 break;

1071 }

1072 return true;

1073}

1074

1079 RISCVVPseudosTable::getPseudoInfo(MI->getOpcode());

1080 if (RVV)

1081 return false;

1082

1084

1087 assert(TRI && "TargetRegisterInfo expected");

1088

1091 unsigned NumOps = MI->getNumExplicitOperands();

1092

1093

1094

1109

1110 bool hasVLOutput = RISCVInstrInfo::isFaultOnlyFirstLoad(*MI);

1111 for (unsigned OpNo = 0; OpNo != NumOps; ++OpNo) {

1113

1114 if (hasVLOutput && OpNo == 1)

1115 continue;

1116

1117

1118 if (OpNo == MI->getNumExplicitDefs() && MO.isReg() && MO.isTied()) {

1120 "Expected tied to first def.");

1122

1123

1125 0 &&

1127 continue;

1128 }

1129

1132 default:

1136

1137 if (RISCV::VRM2RegClass.contains(Reg) ||

1140 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);

1141 assert(Reg && "Subregister does not exist");

1142 } else if (RISCV::FPR16RegClass.contains(Reg)) {

1144 TRI->getMatchingSuperReg(Reg, RISCV::sub_16, &RISCV::FPR32RegClass);

1145 assert(Reg && "Subregister does not exist");

1146 } else if (RISCV::FPR64RegClass.contains(Reg)) {

1147 Reg = TRI->getSubReg(Reg, RISCV::sub_32);

1148 assert(Reg && "Superregister does not exist");

1149 } else if (RISCV::VRN2M1RegClass.contains(Reg) ||

1160 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);

1161 assert(Reg && "Subregister does not exist");

1162 }

1163

1165 break;

1166 }

1169 break;

1170 }

1172 }

1173

1174

1175

1179 RISCV::VMV0RegClassID &&

1180 "Expected only mask operand to be missing");

1182 }

1183

1185 return true;

1186}

1187

1188void RISCVAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {

1190 return;

1191

1193

1194 for (const MachineOperand &MO : MI->operands()) {

1195 MCOperand MCOp;

1196 if (lowerOperand(MO, MCOp))

1198 }

1199}

1200

1201void RISCVAsmPrinter::emitMachineConstantPoolValue(

1202 MachineConstantPoolValue *MCPV) {

1203 auto *RCPV = static_cast<RISCVConstantPoolValue *>(MCPV);

1205

1206 if (RCPV->isGlobalValue()) {

1207 auto *GV = RCPV->getGlobalValue();

1208 MCSym = getSymbol(GV);

1209 } else {

1210 assert(RCPV->isExtSymbol() && "unrecognized constant pool type");

1211 auto Sym = RCPV->getSymbol();

1212 MCSym = GetExternalSymbolSymbol(Sym);

1213 }

1214

1216 uint64_t Size = getDataLayout().getTypeAllocSize(RCPV->getType());

1218}

1219

1220char RISCVAsmPrinter::ID = 0;

1221

1222INITIALIZE_PASS(RISCVAsmPrinter, "riscv-asm-printer", "RISC-V Assembly Printer",

1223 false, false)

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

const TargetInstrInfo & TII

static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)

This file implements a class to represent arbitrary precision integral constant values and operations...

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")

#define LLVM_EXTERNAL_VISIBILITY

Module.h This file contains the declarations for the Module class.

const size_t AbstractManglingParser< Derived, Alloc >::NumOps

static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, const AsmPrinter &AP)

print mir2vec MIR2Vec Vocabulary Printer Pass

Machine Check Debug Module

This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...

Register const TargetRegisterInfo * TRI

Promote Memory to Register

#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)

static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, const RISCVSubtarget *STI)

Definition RISCVAsmPrinter.cpp:1075

LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter()

Definition RISCVAsmPrinter.cpp:616

static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)

This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...

#define STATISTIC(VARNAME, DESC)

static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")

static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")

This class is intended to be used as a driving class for all asm writers.

MCContext & OutContext

This is the context for the output file that we are streaming.

virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)

Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...

virtual void emitFunctionEntryLabel()

EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.

virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)

Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.

static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())

static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)

Context object for machine code objects.

Base class for the full range of assembler expressions which are needed for parsing.

Instances of this class represent a single low-level machine instruction.

unsigned getNumOperands() const

unsigned getOpcode() const

void addOperand(const MCOperand Op)

void setOpcode(unsigned Op)

Describe properties that are true of each instruction in the target description file.

unsigned getNumOperands() const

Return the number of declared MachineOperands for this MachineInstruction.

ArrayRef< MCOperandInfo > operands() const

int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const

Returns the value of the specified operand constraint if it is present.

Instances of this class represent operands of the MCInst class.

static MCOperand createExpr(const MCExpr *Val)

static MCOperand createReg(MCRegister Reg)

static MCOperand createImm(int64_t Val)

const MCExpr * getExpr() const

static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())

Streaming machine code generation interface.

virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)

Emit the given Instruction into the current section.

virtual bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute)=0

Add the given Attribute to Symbol.

MCContext & getContext() const

void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())

virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())

Emit a label for Symbol into the current section.

MCTargetStreamer * getTargetStreamer()

virtual void emitCodeAlignment(Align Alignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit=0)

Emit nops until the byte alignment ByteAlignment is reached.

virtual void switchSection(MCSection *Section, uint32_t Subsec=0)

Set the current section where code is being emitted to Section.

bool hasFeature(unsigned Feature) const

FeatureBitset ToggleFeature(uint64_t FB)

Toggle a feature and return the re-computed feature bits.

static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())

MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...

LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const

print - Print the value to the stream OS.

StringRef getName() const

getName - Get the symbol name.

MachineInstrBundleIterator< const MachineInstr > const_iterator

LLVM_ABI MCSymbol * getSymbol() const

Return the MCSymbol for this basic block.

const TargetSubtargetInfo & getSubtarget() const

getSubtarget - Return the subtarget for which this machine code is being compiled.

Ty * getInfo()

getInfo - Keep track of various per-function pieces of information for backends that would like to do...

Representation of each machine instruction.

bool isNonTemporal() const

Flags getFlags() const

Return the raw flags of the source value,.

MachineOperand class - Representation of each machine instruction operand.

const GlobalValue * getGlobal() const

bool isReg() const

isReg - Tests if this is a MO_Register operand.

MachineBasicBlock * getMBB() const

bool isImm() const

isImm - Tests if this is a MO_Immediate operand.

bool isJTI() const

isJTI - Tests if this is a MO_JumpTableIndex operand.

const BlockAddress * getBlockAddress() const

unsigned getTargetFlags() const

bool isGlobal() const

isGlobal - Tests if this is a MO_GlobalAddress operand.

MachineOperandType getType() const

getType - Returns the MachineOperandType for this operand.

const char * getSymbolName() const

Register getReg() const

getReg - Returns the register number.

MCSymbol * getMCSymbol() const

@ MO_Immediate

Immediate operand.

@ MO_ConstantPoolIndex

Address of indexed Constant in Constant Pool.

@ MO_MCSymbol

MCSymbol reference (for debug/eh info)

@ MO_GlobalAddress

Address of a global value.

@ MO_RegisterMask

Mask of preserved registers.

@ MO_BlockAddress

Address of a basic block.

@ MO_MachineBasicBlock

MachineBasicBlock reference.

@ MO_Register

Register operand.

@ MO_ExternalSymbol

Name of external global symbol.

@ MO_JumpTableIndex

Address of indexed Jump Table for switch.

int64_t getOffset() const

Return the offset from the symbol in this operand.

bool isMBB() const

isMBB - Tests if this is a MO_MachineBasicBlock operand.

static LLVM_ABI bool isSupportedExtensionFeature(StringRef Ext)

static LLVM_ABI llvm::Expected< std::unique_ptr< RISCVISAInfo > > parseArchString(StringRef Arch, bool EnableExperimentalExtension, bool ExperimentalExtensionVersionCheck=true)

Parse RISC-V ISA info from arch string.

static const char * getRegisterName(MCRegister Reg)

bool isRegisterReservedByUser(Register i) const override

const RISCVRegisterInfo * getRegisterInfo() const override

const RISCVInstrInfo * getInstrInfo() const override

void emitNoteGnuPropertySection(const uint32_t Feature1And)

virtual void emitDirectiveVariantCC(MCSymbol &Symbol)

void emitTargetAttributes(const MCSubtargetInfo &STI, bool EmitStackAlign)

void setFlagsFromFeatures(const MCSubtargetInfo &STI)

void setTargetABI(RISCVABI::ABI ABI)

virtual void emitDirectiveOptionArch(ArrayRef< RISCVOptionArchArg > Args)

virtual void finishAttributeSection()

virtual void emitDirectiveOptionPush()

Wrapper class representing virtual and physical registers.

reference emplace_back(ArgTypes &&... Args)

LLVM_ABI void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)

Generate a stackmap record for a statepoint instruction.

LLVM_ABI void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)

Generate a stackmap record for a patchpoint instruction.

LLVM_ABI void recordStackMap(const MCSymbol &L, const MachineInstr &MI)

Generate a stackmap record for a stackmap instruction.

TargetInstrInfo - Interface to description of machine instruction set.

TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...

#define llvm_unreachable(msg)

Marks that the current location is not supposed to be reachable.

constexpr char Align[]

Key for Kernel::Arg::Metadata::mAlign.

@ GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS

ABI getTargetABI(StringRef ABIName)

static bool hasRoundModeOp(uint64_t TSFlags)

static bool hasTWidenOp(uint64_t TSFlags)

static bool isTiedPseudo(uint64_t TSFlags)

static bool hasTKOp(uint64_t TSFlags)

static bool hasVLOp(uint64_t TSFlags)

static bool hasTMOp(uint64_t TSFlags)

static bool hasVecPolicyOp(uint64_t TSFlags)

static bool hasSEWOp(uint64_t TSFlags)

void generateMCInstSeq(int64_t Val, const MCSubtargetInfo &STI, MCRegister DestReg, SmallVectorImpl< MCInst > &Insts)

bool compress(MCInst &OutInst, const MCInst &MI, const MCSubtargetInfo &STI)

void emitInstruction(MCObjectStreamer &, const MCInst &Inst, const MCSubtargetInfo &STI)

std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)

Extract a Value from Metadata.

This is an optimization pass for GlobalISel generic memory operations.

bool errorToBool(Error Err)

Helper for converting an Error to a bool.

static const MachineMemOperand::Flags MONontemporalBit1

Target & getTheRISCV32Target()

static const MachineMemOperand::Flags MONontemporalBit0

std::string utostr(uint64_t X, bool isNeg=false)

Target & getTheRISCV64beTarget()

auto dyn_cast_or_null(const Y &Val)

LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)

class LLVM_GSL_OWNER SmallVector

Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...

Target & getTheRISCV64Target()

OutputIt move(R &&Range, OutputIt Out)

Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.

constexpr int64_t SignExtend64(uint64_t x)

Sign-extend the number in the bottom B bits of X to a 64-bit integer.

const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures]

@ MCSA_ELF_TypeFunction

.type _foo, STT_FUNC # aka @function

@ MCSA_Hidden

.hidden (ELF)

Target & getTheRISCV32beTarget()

RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...

Used to provide key value pairs for feature and CPU bit flags.