LLVM 22.0.0git
RISCVAsmPrinter.cpp
Go to the documentation of this file.
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
19#include "RISCV.h"
22#include "RISCVRegisterInfo.h"
24#include "llvm/ADT/APInt.h"
25#include "llvm/ADT/Statistic.h"
31#include "llvm/IR/Module.h"
32#include "llvm/MC/MCAsmInfo.h"
33#include "llvm/MC/MCContext.h"
34#include "llvm/MC/MCInst.h"
38#include "llvm/MC/MCStreamer.h"
39#include "llvm/MC/MCSymbol.h"
45
46using namespace llvm;
47
48#define DEBUG_TYPE "asm-printer"
49
50STATISTIC(RISCVNumInstrsCompressed,
51 "Number of RISC-V Compressed instructions emitted");
52
53namespace llvm {
54extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures];
55} // namespace llvm
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<MCStreamer> 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
83 void emitInstruction(const MachineInstr *MI) override;
84
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 // Returns whether Inst is compressed.
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 // Wrapper needed for tblgenned pseudo lowering.
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 // XRay Support
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 bool lowerToMCInst(const MachineInstr *MI, MCInst &OutMI);
130};
131}
132
133void RISCVAsmPrinter::LowerSTACKMAP(MCStreamer &OutStreamer, StackMaps &SM,
134 const MachineInstr &MI) {
135 unsigned NOPBytes = STI->hasStdExtZca() ? 2 : 4;
136 unsigned NumNOPBytes = StackMapOpers(&MI).getNumPatchBytes();
137
138 auto &Ctx = OutStreamer.getContext();
139 MCSymbol *MILabel = Ctx.createTempSymbol();
140 OutStreamer.emitLabel(MILabel);
141
142 SM.recordStackMap(*MILabel, MI);
143 assert(NumNOPBytes % NOPBytes == 0 &&
144 "Invalid number of NOP bytes requested!");
145
146 // Scan ahead to trim the shadow.
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 // Emit nops.
161 emitNops(NumNOPBytes / NOPBytes);
162}
163
164// Lower a patchpoint of the form:
165// [<def>], <id>, <numBytes>, <target>, <numArgs>
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();
172 OutStreamer.emitLabel(MILabel);
173 SM.recordPatchPoint(*MILabel, MI);
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 // Materialize the jump address:
187 RISCVMatInt::generateMCInstSeq(CallTarget, *STI, RISCV::X1, Seq);
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 // Emit padding.
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 // Lower call target and choose correct opcode
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;
237 CallTargetMCOp = MCOperand::createImm(CallTarget.getImm());
238 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JAL)
239 .addReg(RISCV::X1)
240 .addOperand(CallTargetMCOp));
241 break;
243 CallTargetMCOp = MCOperand::createReg(CallTarget.getReg());
244 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JALR)
245 .addReg(RISCV::X1)
246 .addOperand(CallTargetMCOp)
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();
257 OutStreamer.emitLabel(MILabel);
258 SM.recordStatepoint(*MILabel, MI);
259}
260
261bool RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst,
262 const MCSubtargetInfo &SubtargetInfo) {
263 MCInst CInst;
264 bool Res = RISCVRVC::compress(CInst, Inst, SubtargetInfo);
265 if (Res)
266 ++RISCVNumInstrsCompressed;
267 S.emitInstruction(Res ? CInst : Inst, SubtargetInfo);
268 return Res;
269}
270
271// Simple pseudo-instructions have their lowering (with expansion to real
272// instructions) auto-generated.
273#include "RISCVGenMCPseudoLowering.inc"
274
275// If the target supports Zihintntl and the instruction has a nontemporal
276// MachineMemOperand, emit an NTLH hint instruction before it.
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());
285 if (!MMO->isNonTemporal())
286 return;
287
288 unsigned NontemporalMode = 0;
289 if (MMO->getFlags() & MONontemporalBit0)
290 NontemporalMode += 0b1;
291 if (MMO->getFlags() & MONontemporalBit1)
292 NontemporalMode += 0b10;
293
294 MCInst Hint;
295 if (STI->hasStdExtZca())
296 Hint.setOpcode(RISCV::C_ADD);
297 else
298 Hint.setOpcode(RISCV::ADD);
299
300 Hint.addOperand(MCOperand::createReg(RISCV::X0));
301 Hint.addOperand(MCOperand::createReg(RISCV::X0));
302 Hint.addOperand(MCOperand::createReg(RISCV::X2 + NontemporalMode));
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 // Do any auto-generated pseudo lowerings.
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 // patchable-function-entry is handled in lowerToMCInst
333 // Therefore, we break out of the switch statement if we encounter it here.
334 const Function &F = MI->getParent()->getParent()->getFunction();
335 if (F.hasFnAttribute("patchable-function-entry"))
336 break;
337
338 LowerPATCHABLE_FUNCTION_ENTER(MI);
339 return;
340 }
341 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
342 LowerPATCHABLE_FUNCTION_EXIT(MI);
343 return;
344 case TargetOpcode::PATCHABLE_TAIL_CALL:
345 LowerPATCHABLE_TAIL_CALL(MI);
346 return;
347 }
348
349 MCInst OutInst;
350 if (!lowerToMCInst(MI, OutInst))
351 EmitToStreamer(*OutStreamer, OutInst);
352}
353
354bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
355 const char *ExtraCode, raw_ostream &OS) {
356 // First try the generic code, which knows about modifiers like 'c' and 'n'.
357 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))
358 return false;
359
360 const MachineOperand &MO = MI->getOperand(OpNo);
361 if (ExtraCode && ExtraCode[0]) {
362 if (ExtraCode[1] != 0)
363 return true; // Unknown modifier.
364
365 switch (ExtraCode[0]) {
366 default:
367 return true; // Unknown modifier.
368 case 'z': // Print zero register if zero, regular printing otherwise.
369 if (MO.isImm() && MO.getImm() == 0) {
371 return false;
372 }
373 break;
374 case 'i': // Literal 'i' if operand is not a register.
375 if (!MO.isReg())
376 OS << 'i';
377 return false;
378 case 'N': // Print the register encoding as an integer (0-31)
379 if (!MO.isReg())
380 return true;
381
382 const RISCVRegisterInfo *TRI = STI->getRegisterInfo();
383 OS << TRI->getEncodingValue(MO.getReg());
384 return false;
385 }
386 }
387
388 switch (MO.getType()) {
390 OS << MO.getImm();
391 return false;
394 return false;
396 PrintSymbolOperand(MO, OS);
397 return false;
399 MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());
400 Sym->print(OS, MAI);
401 return false;
402 }
403 default:
404 break;
405 }
406
407 return true;
408}
409
410bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
411 unsigned OpNo,
412 const char *ExtraCode,
413 raw_ostream &OS) {
414 if (ExtraCode)
415 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);
416
417 const MachineOperand &AddrReg = MI->getOperand(OpNo);
418 assert(MI->getNumOperands() > OpNo + 1 && "Expected additional operand");
419 const MachineOperand &Offset = MI->getOperand(OpNo + 1);
420 // All memory operands should have a register and an immediate operand (see
421 // RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand).
422 if (!AddrReg.isReg())
423 return true;
424 if (!Offset.isImm() && !Offset.isGlobal() && !Offset.isBlockAddress() &&
425 !Offset.isMCSymbol())
426 return true;
427
428 MCOperand MCO;
429 if (!lowerOperand(Offset, MCO))
430 return true;
431
432 if (Offset.isImm())
433 OS << MCO.getImm();
434 else if (Offset.isGlobal() || Offset.isBlockAddress() || Offset.isMCSymbol())
435 MAI->printExpr(OS, *MCO.getExpr());
436
437 if (Offset.isMCSymbol())
438 MMI->getContext().registerInlineAsmLabel(Offset.getMCSymbol());
439 if (Offset.isBlockAddress()) {
440 const BlockAddress *BA = Offset.getBlockAddress();
441 MCSymbol *Sym = GetBlockAddressSymbol(BA);
442 MMI->getContext().registerInlineAsmLabel(Sym);
443 }
444
445 OS << "(" << RISCVInstPrinter::getRegisterName(AddrReg.getReg()) << ")";
446 return false;
447}
448
449bool RISCVAsmPrinter::emitDirectiveOptionArch() {
451 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
452 SmallVector<RISCVOptionArchArg> NeedEmitStdOptionArgs;
453 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();
454 for (const auto &Feature : RISCVFeatureKV) {
455 if (STI->hasFeature(Feature.Value) == MCSTI.hasFeature(Feature.Value))
456 continue;
457
459 continue;
460
461 auto Delta = STI->hasFeature(Feature.Value) ? RISCVOptionArchArgType::Plus
462 : RISCVOptionArchArgType::Minus;
463 NeedEmitStdOptionArgs.emplace_back(Delta, Feature.Key);
464 }
465 if (!NeedEmitStdOptionArgs.empty()) {
467 RTS.emitDirectiveOptionArch(NeedEmitStdOptionArgs);
468 return true;
469 }
470
471 return false;
472}
473
474bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
475 STI = &MF.getSubtarget<RISCVSubtarget>();
477 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
478
479 bool EmittedOptionArch = emitDirectiveOptionArch();
480
481 SetupMachineFunction(MF);
482 emitFunctionBody();
483
484 // Emit the XRay table
485 emitXRayTable();
486
487 if (EmittedOptionArch)
488 RTS.emitDirectiveOptionPop();
489 return false;
490}
491
492void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr *MI) {
493 emitSled(MI, SledKind::FUNCTION_ENTER);
494}
495
496void RISCVAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr *MI) {
497 emitSled(MI, SledKind::FUNCTION_EXIT);
498}
499
500void RISCVAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr *MI) {
501 emitSled(MI, SledKind::TAIL_CALL);
502}
503
504void RISCVAsmPrinter::emitSled(const MachineInstr *MI, SledKind Kind) {
505 // We want to emit the jump instruction and the nops constituting the sled.
506 // The format is as follows:
507 // .Lxray_sled_N
508 // ALIGN
509 // J .tmpN
510 // 21 or 33 C.NOP instructions
511 // .tmpN
512
513 // The following variable holds the count of the number of NOPs to be patched
514 // in for XRay instrumentation during compilation.
515 // Note that RV64 and RV32 each has a sled of 68 and 44 bytes, respectively.
516 // Assuming we're using JAL to jump to .tmpN, then we only need
517 // (68 - 4)/2 = 32 NOPs for RV64 and (44 - 4)/2 = 20 for RV32. However, there
518 // is a chance that we'll use C.JAL instead, so an additional NOP is needed.
519 const uint8_t NoopsInSledCount = STI->is64Bit() ? 33 : 21;
520
521 OutStreamer->emitCodeAlignment(Align(4), STI);
522 auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
523 OutStreamer->emitLabel(CurSled);
524 auto Target = OutContext.createTempSymbol();
525
526 const MCExpr *TargetExpr = MCSymbolRefExpr::create(Target, OutContext);
527
528 // Emit "J bytes" instruction, which jumps over the nop sled to the actual
529 // start of function.
530 EmitToStreamer(
531 *OutStreamer,
532 MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addExpr(TargetExpr));
533
534 // Emit NOP instructions
535 for (int8_t I = 0; I < NoopsInSledCount; ++I)
536 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
537 .addReg(RISCV::X0)
538 .addReg(RISCV::X0)
539 .addImm(0));
540
541 OutStreamer->emitLabel(Target);
542 recordSled(CurSled, *MI, Kind, 2);
543}
544
545void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) {
547 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
548 if (const MDString *ModuleTargetABI =
549 dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi")))
550 RTS.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI->getString()));
551
552 MCSubtargetInfo SubtargetInfo = *TM.getMCSubtargetInfo();
553
554 // Use module flag to update feature bits.
555 if (auto *MD = dyn_cast_or_null<MDNode>(M.getModuleFlag("riscv-isa"))) {
556 for (auto &ISA : MD->operands()) {
557 if (auto *ISAString = dyn_cast_or_null<MDString>(ISA)) {
559 ISAString->getString(), /*EnableExperimentalExtension=*/true,
560 /*ExperimentalExtensionVersionCheck=*/true);
561 if (!errorToBool(ParseResult.takeError())) {
562 auto &ISAInfo = *ParseResult;
563 for (const auto &Feature : RISCVFeatureKV) {
564 if (ISAInfo->hasExtension(Feature.Key) &&
565 !SubtargetInfo.hasFeature(Feature.Value))
566 SubtargetInfo.ToggleFeature(Feature.Key);
567 }
568 }
569 }
570 }
571
572 RTS.setFlagsFromFeatures(SubtargetInfo);
573 }
574
575 if (TM.getTargetTriple().isOSBinFormatELF())
576 emitAttributes(SubtargetInfo);
577}
578
579void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) {
581 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
582
583 if (TM.getTargetTriple().isOSBinFormatELF()) {
585 emitNoteGnuProperty(M);
586 }
587 EmitHwasanMemaccessSymbols(M);
588}
589
590void RISCVAsmPrinter::emitAttributes(const MCSubtargetInfo &SubtargetInfo) {
592 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
593 // Use MCSubtargetInfo from TargetMachine. Individual functions may have
594 // attributes that differ from other functions in the module and we have no
595 // way to know which function is correct.
596 RTS.emitTargetAttributes(SubtargetInfo, /*EmitStackAlign*/ true);
597}
598
599void RISCVAsmPrinter::emitFunctionEntryLabel() {
600 const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>();
601 if (RMFI->isVectorCall()) {
602 auto &RTS =
603 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
604 RTS.emitDirectiveVariantCC(*CurrentFnSym);
605 }
607}
608
609// Force static initialization.
616}
617
618void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {
619 Register Reg = MI.getOperand(0).getReg();
620 uint32_t AccessInfo = MI.getOperand(1).getImm();
621 MCSymbol *&Sym =
622 HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)];
623 if (!Sym) {
624 // FIXME: Make this work on non-ELF.
625 if (!TM.getTargetTriple().isOSBinFormatELF())
626 report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");
627
628 std::string SymName = "__hwasan_check_x" + utostr(Reg - RISCV::X0) + "_" +
629 utostr(AccessInfo) + "_short";
630 Sym = OutContext.getOrCreateSymbol(SymName);
631 }
632 auto Res = MCSymbolRefExpr::create(Sym, OutContext);
633 auto Expr = MCSpecifierExpr::create(Res, ELF::R_RISCV_CALL_PLT, OutContext);
634
635 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr));
636}
637
638void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
639 Register AddrReg = MI.getOperand(0).getReg();
640 assert(std::next(MI.getIterator())->isCall() &&
641 "KCFI_CHECK not followed by a call instruction");
642 assert(std::next(MI.getIterator())->getOperand(0).getReg() == AddrReg &&
643 "KCFI_CHECK call target doesn't match call operand");
644
645 // Temporary registers for comparing the hashes. If a register is used
646 // for the call target, or reserved by the user, we can clobber another
647 // temporary register as the check is immediately followed by the
648 // call. The check defaults to X6/X7, but can fall back to X28-X31 if
649 // needed.
650 unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7};
651 unsigned NextReg = RISCV::X28;
652 auto isRegAvailable = [&](unsigned Reg) {
653 return Reg != AddrReg && !STI->isRegisterReservedByUser(Reg);
654 };
655 for (auto &Reg : ScratchRegs) {
656 if (isRegAvailable(Reg))
657 continue;
658 while (!isRegAvailable(NextReg))
659 ++NextReg;
660 Reg = NextReg++;
661 if (Reg > RISCV::X31)
662 report_fatal_error("Unable to find scratch registers for KCFI_CHECK");
663 }
664
665 if (AddrReg == RISCV::X0) {
666 // Checking X0 makes no sense. Instead of emitting a load, zero
667 // ScratchRegs[0].
668 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)
669 .addReg(ScratchRegs[0])
670 .addReg(RISCV::X0)
671 .addImm(0));
672 } else {
673 // Adjust the offset for patchable-function-prefix. This assumes that
674 // patchable-function-prefix is the same for all functions.
675 int NopSize = STI->hasStdExtZca() ? 2 : 4;
676 int64_t PrefixNops = 0;
677 (void)MI.getMF()
678 ->getFunction()
679 .getFnAttribute("patchable-function-prefix")
680 .getValueAsString()
681 .getAsInteger(10, PrefixNops);
682
683 // Load the target function type hash.
684 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW)
685 .addReg(ScratchRegs[0])
686 .addReg(AddrReg)
687 .addImm(-(PrefixNops * NopSize + 4)));
688 }
689
690 // Load the expected 32-bit type hash.
691 const int64_t Type = MI.getOperand(1).getImm();
692 const int64_t Hi20 = ((Type + 0x800) >> 12) & 0xFFFFF;
693 const int64_t Lo12 = SignExtend64<12>(Type);
694 if (Hi20) {
695 EmitToStreamer(
696 *OutStreamer,
697 MCInstBuilder(RISCV::LUI).addReg(ScratchRegs[1]).addImm(Hi20));
698 }
699 if (Lo12 || Hi20 == 0) {
700 EmitToStreamer(*OutStreamer,
701 MCInstBuilder((STI->hasFeature(RISCV::Feature64Bit) && Hi20)
702 ? RISCV::ADDIW
703 : RISCV::ADDI)
704 .addReg(ScratchRegs[1])
705 .addReg(ScratchRegs[1])
706 .addImm(Lo12));
707 }
708
709 // Compare the hashes and trap if there's a mismatch.
710 MCSymbol *Pass = OutContext.createTempSymbol();
711 EmitToStreamer(*OutStreamer,
712 MCInstBuilder(RISCV::BEQ)
713 .addReg(ScratchRegs[0])
714 .addReg(ScratchRegs[1])
715 .addExpr(MCSymbolRefExpr::create(Pass, OutContext)));
716
717 MCSymbol *Trap = OutContext.createTempSymbol();
718 OutStreamer->emitLabel(Trap);
719 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::EBREAK));
720 emitKCFITrapEntry(*MI.getMF(), Trap);
721 OutStreamer->emitLabel(Pass);
722}
723
724void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {
725 if (HwasanMemaccessSymbols.empty())
726 return;
727
728 assert(TM.getTargetTriple().isOSBinFormatELF());
729 // Use MCSubtargetInfo from TargetMachine. Individual functions may have
730 // attributes that differ from other functions in the module and we have no
731 // way to know which function is correct.
732 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();
733
734 MCSymbol *HwasanTagMismatchV2Sym =
735 OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2");
736 // Annotate symbol as one having incompatible calling convention, so
737 // run-time linkers can instead eagerly bind this function.
738 auto &RTS =
739 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
740 RTS.emitDirectiveVariantCC(*HwasanTagMismatchV2Sym);
741
742 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =
743 MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext);
744 auto Expr = MCSpecifierExpr::create(HwasanTagMismatchV2Ref,
745 ELF::R_RISCV_CALL_PLT, OutContext);
746
747 for (auto &P : HwasanMemaccessSymbols) {
748 unsigned Reg = std::get<0>(P.first);
749 uint32_t AccessInfo = std::get<1>(P.first);
750 MCSymbol *Sym = P.second;
751
752 unsigned Size =
753 1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf);
754 OutStreamer->switchSection(OutContext.getELFSection(
755 ".text.hot", ELF::SHT_PROGBITS,
757 /*IsComdat=*/true));
758
760 OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak);
761 OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden);
762 OutStreamer->emitLabel(Sym);
763
764 // Extract shadow offset from ptr
765 EmitToStreamer(
766 *OutStreamer,
767 MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(Reg).addImm(8),
768 MCSTI);
769 EmitToStreamer(*OutStreamer,
770 MCInstBuilder(RISCV::SRLI)
771 .addReg(RISCV::X6)
772 .addReg(RISCV::X6)
773 .addImm(12),
774 MCSTI);
775 // load shadow tag in X6, X5 contains shadow base
776 EmitToStreamer(*OutStreamer,
777 MCInstBuilder(RISCV::ADD)
778 .addReg(RISCV::X6)
779 .addReg(RISCV::X5)
780 .addReg(RISCV::X6),
781 MCSTI);
782 EmitToStreamer(
783 *OutStreamer,
784 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
785 MCSTI);
786 // Extract tag from pointer and compare it with loaded tag from shadow
787 EmitToStreamer(
788 *OutStreamer,
789 MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(Reg).addImm(56),
790 MCSTI);
791 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();
792 // X7 contains tag from the pointer, while X6 contains tag from memory
793 EmitToStreamer(*OutStreamer,
794 MCInstBuilder(RISCV::BNE)
795 .addReg(RISCV::X7)
796 .addReg(RISCV::X6)
798 HandleMismatchOrPartialSym, OutContext)),
799 MCSTI);
800 MCSymbol *ReturnSym = OutContext.createTempSymbol();
801 OutStreamer->emitLabel(ReturnSym);
802 EmitToStreamer(*OutStreamer,
803 MCInstBuilder(RISCV::JALR)
804 .addReg(RISCV::X0)
805 .addReg(RISCV::X1)
806 .addImm(0),
807 MCSTI);
808 OutStreamer->emitLabel(HandleMismatchOrPartialSym);
809
810 EmitToStreamer(*OutStreamer,
811 MCInstBuilder(RISCV::ADDI)
812 .addReg(RISCV::X28)
813 .addReg(RISCV::X0)
814 .addImm(16),
815 MCSTI);
816 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol();
817 EmitToStreamer(
818 *OutStreamer,
819 MCInstBuilder(RISCV::BGEU)
820 .addReg(RISCV::X6)
821 .addReg(RISCV::X28)
822 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
823 MCSTI);
824
825 EmitToStreamer(
826 *OutStreamer,
827 MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(Reg).addImm(0xF),
828 MCSTI);
829
830 if (Size != 1)
831 EmitToStreamer(*OutStreamer,
832 MCInstBuilder(RISCV::ADDI)
833 .addReg(RISCV::X28)
834 .addReg(RISCV::X28)
835 .addImm(Size - 1),
836 MCSTI);
837 EmitToStreamer(
838 *OutStreamer,
839 MCInstBuilder(RISCV::BGE)
840 .addReg(RISCV::X28)
841 .addReg(RISCV::X6)
842 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),
843 MCSTI);
844
845 EmitToStreamer(
846 *OutStreamer,
847 MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(Reg).addImm(0xF),
848 MCSTI);
849 EmitToStreamer(
850 *OutStreamer,
851 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0),
852 MCSTI);
853 EmitToStreamer(*OutStreamer,
854 MCInstBuilder(RISCV::BEQ)
855 .addReg(RISCV::X6)
856 .addReg(RISCV::X7)
857 .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),
858 MCSTI);
859
860 OutStreamer->emitLabel(HandleMismatchSym);
861
862 // | Previous stack frames... |
863 // +=================================+ <-- [SP + 256]
864 // | ... |
865 // | |
866 // | Stack frame space for x12 - x31.|
867 // | |
868 // | ... |
869 // +---------------------------------+ <-- [SP + 96]
870 // | Saved x11(arg1), as |
871 // | __hwasan_check_* clobbers it. |
872 // +---------------------------------+ <-- [SP + 88]
873 // | Saved x10(arg0), as |
874 // | __hwasan_check_* clobbers it. |
875 // +---------------------------------+ <-- [SP + 80]
876 // | |
877 // | Stack frame space for x9. |
878 // +---------------------------------+ <-- [SP + 72]
879 // | |
880 // | Saved x8(fp), as |
881 // | __hwasan_check_* clobbers it. |
882 // +---------------------------------+ <-- [SP + 64]
883 // | ... |
884 // | |
885 // | Stack frame space for x2 - x7. |
886 // | |
887 // | ... |
888 // +---------------------------------+ <-- [SP + 16]
889 // | Return address (x1) for caller |
890 // | of __hwasan_check_*. |
891 // +---------------------------------+ <-- [SP + 8]
892 // | Reserved place for x0, possibly |
893 // | junk, since we don't save it. |
894 // +---------------------------------+ <-- [x2 / SP]
895
896 // Adjust sp
897 EmitToStreamer(*OutStreamer,
898 MCInstBuilder(RISCV::ADDI)
899 .addReg(RISCV::X2)
900 .addReg(RISCV::X2)
901 .addImm(-256),
902 MCSTI);
903
904 // store x10(arg0) by new sp
905 EmitToStreamer(*OutStreamer,
906 MCInstBuilder(RISCV::SD)
907 .addReg(RISCV::X10)
908 .addReg(RISCV::X2)
909 .addImm(8 * 10),
910 MCSTI);
911 // store x11(arg1) by new sp
912 EmitToStreamer(*OutStreamer,
913 MCInstBuilder(RISCV::SD)
914 .addReg(RISCV::X11)
915 .addReg(RISCV::X2)
916 .addImm(8 * 11),
917 MCSTI);
918
919 // store x8(fp) by new sp
920 EmitToStreamer(
921 *OutStreamer,
922 MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 *
923 8),
924 MCSTI);
925 // store x1(ra) by new sp
926 EmitToStreamer(
927 *OutStreamer,
928 MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 *
929 8),
930 MCSTI);
931 if (Reg != RISCV::X10)
932 EmitToStreamer(
933 *OutStreamer,
934 MCInstBuilder(RISCV::ADDI).addReg(RISCV::X10).addReg(Reg).addImm(0),
935 MCSTI);
936 EmitToStreamer(*OutStreamer,
937 MCInstBuilder(RISCV::ADDI)
938 .addReg(RISCV::X11)
939 .addReg(RISCV::X0)
940 .addImm(AccessInfo & HWASanAccessInfo::RuntimeMask),
941 MCSTI);
942
943 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr),
944 MCSTI);
945 }
946}
947
948void RISCVAsmPrinter::emitNoteGnuProperty(const Module &M) {
949 if (const Metadata *const Flag = M.getModuleFlag("cf-protection-return");
950 Flag && !mdconst::extract<ConstantInt>(Flag)->isZero()) {
952 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());
954 }
955}
956
958 const AsmPrinter &AP) {
959 MCContext &Ctx = AP.OutContext;
960 RISCV::Specifier Kind;
961
962 switch (MO.getTargetFlags()) {
963 default:
964 llvm_unreachable("Unknown target flag on GV operand");
965 case RISCVII::MO_None:
966 Kind = RISCV::S_None;
967 break;
968 case RISCVII::MO_CALL:
969 Kind = ELF::R_RISCV_CALL_PLT;
970 break;
971 case RISCVII::MO_LO:
972 Kind = RISCV::S_LO;
973 break;
974 case RISCVII::MO_HI:
975 Kind = ELF::R_RISCV_HI20;
976 break;
978 Kind = RISCV::S_PCREL_LO;
979 break;
981 Kind = ELF::R_RISCV_PCREL_HI20;
982 break;
984 Kind = ELF::R_RISCV_GOT_HI20;
985 break;
987 Kind = RISCV::S_TPREL_LO;
988 break;
990 Kind = ELF::R_RISCV_TPREL_HI20;
991 break;
993 Kind = ELF::R_RISCV_TPREL_ADD;
994 break;
996 Kind = ELF::R_RISCV_TLS_GOT_HI20;
997 break;
999 Kind = ELF::R_RISCV_TLS_GD_HI20;
1000 break;
1002 Kind = ELF::R_RISCV_TLSDESC_HI20;
1003 break;
1005 Kind = ELF::R_RISCV_TLSDESC_LOAD_LO12;
1006 break;
1008 Kind = ELF::R_RISCV_TLSDESC_ADD_LO12;
1009 break;
1011 Kind = ELF::R_RISCV_TLSDESC_CALL;
1012 break;
1013 }
1014
1015 const MCExpr *ME = MCSymbolRefExpr::create(Sym, Ctx);
1016
1017 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())
1019 ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);
1020
1021 if (Kind != RISCV::S_None)
1022 ME = MCSpecifierExpr::create(ME, Kind, Ctx);
1023 return MCOperand::createExpr(ME);
1024}
1025
1026bool RISCVAsmPrinter::lowerOperand(const MachineOperand &MO,
1027 MCOperand &MCOp) const {
1028 switch (MO.getType()) {
1029 default:
1030 report_fatal_error("lowerOperand: unknown operand type");
1032 // Ignore all implicit register operands.
1033 if (MO.isImplicit())
1034 return false;
1035 MCOp = MCOperand::createReg(MO.getReg());
1036 break;
1038 // Regmasks are like implicit defs.
1039 return false;
1041 MCOp = MCOperand::createImm(MO.getImm());
1042 break;
1044 MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), *this);
1045 break;
1047 MCOp = lowerSymbolOperand(MO, getSymbolPreferLocal(*MO.getGlobal()), *this);
1048 break;
1050 MCOp = lowerSymbolOperand(MO, GetBlockAddressSymbol(MO.getBlockAddress()),
1051 *this);
1052 break;
1054 MCOp = lowerSymbolOperand(MO, GetExternalSymbolSymbol(MO.getSymbolName()),
1055 *this);
1056 break;
1058 MCOp = lowerSymbolOperand(MO, GetCPISymbol(MO.getIndex()), *this);
1059 break;
1061 MCOp = lowerSymbolOperand(MO, GetJTISymbol(MO.getIndex()), *this);
1062 break;
1064 MCOp = lowerSymbolOperand(MO, MO.getMCSymbol(), *this);
1065 break;
1066 }
1067 return true;
1068}
1069
1071 MCInst &OutMI,
1072 const RISCVSubtarget *STI) {
1074 RISCVVPseudosTable::getPseudoInfo(MI->getOpcode());
1075 if (!RVV)
1076 return false;
1077
1078 OutMI.setOpcode(RVV->BaseInstr);
1079
1080 const TargetInstrInfo *TII = STI->getInstrInfo();
1081 const TargetRegisterInfo *TRI = STI->getRegisterInfo();
1082 assert(TRI && "TargetRegisterInfo expected");
1083
1084 const MCInstrDesc &MCID = MI->getDesc();
1085 uint64_t TSFlags = MCID.TSFlags;
1086 unsigned NumOps = MI->getNumExplicitOperands();
1087
1088 // Skip policy, SEW, VL, VXRM/FRM operands which are the last operands if
1089 // present.
1090 if (RISCVII::hasVecPolicyOp(TSFlags))
1091 --NumOps;
1092 if (RISCVII::hasSEWOp(TSFlags))
1093 --NumOps;
1094 if (RISCVII::hasVLOp(TSFlags))
1095 --NumOps;
1096 if (RISCVII::hasRoundModeOp(TSFlags))
1097 --NumOps;
1098
1099 bool hasVLOutput = RISCVInstrInfo::isFaultOnlyFirstLoad(*MI);
1100 for (unsigned OpNo = 0; OpNo != NumOps; ++OpNo) {
1101 const MachineOperand &MO = MI->getOperand(OpNo);
1102 // Skip vl output. It should be the second output.
1103 if (hasVLOutput && OpNo == 1)
1104 continue;
1105
1106 // Skip passthru op. It should be the first operand after the defs.
1107 if (OpNo == MI->getNumExplicitDefs() && MO.isReg() && MO.isTied()) {
1108 assert(MCID.getOperandConstraint(OpNo, MCOI::TIED_TO) == 0 &&
1109 "Expected tied to first def.");
1110 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
1111 // Skip if the next operand in OutMI is not supposed to be tied. Unless it
1112 // is a _TIED instruction.
1113 if (OutMCID.getOperandConstraint(OutMI.getNumOperands(), MCOI::TIED_TO) <
1114 0 &&
1115 !RISCVII::isTiedPseudo(TSFlags))
1116 continue;
1117 }
1118
1119 MCOperand MCOp;
1120 switch (MO.getType()) {
1121 default:
1122 llvm_unreachable("Unknown operand type");
1124 Register Reg = MO.getReg();
1125
1126 if (RISCV::VRM2RegClass.contains(Reg) ||
1127 RISCV::VRM4RegClass.contains(Reg) ||
1128 RISCV::VRM8RegClass.contains(Reg)) {
1129 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
1130 assert(Reg && "Subregister does not exist");
1131 } else if (RISCV::FPR16RegClass.contains(Reg)) {
1132 Reg =
1133 TRI->getMatchingSuperReg(Reg, RISCV::sub_16, &RISCV::FPR32RegClass);
1134 assert(Reg && "Subregister does not exist");
1135 } else if (RISCV::FPR64RegClass.contains(Reg)) {
1136 Reg = TRI->getSubReg(Reg, RISCV::sub_32);
1137 assert(Reg && "Superregister does not exist");
1138 } else if (RISCV::VRN2M1RegClass.contains(Reg) ||
1139 RISCV::VRN2M2RegClass.contains(Reg) ||
1140 RISCV::VRN2M4RegClass.contains(Reg) ||
1141 RISCV::VRN3M1RegClass.contains(Reg) ||
1142 RISCV::VRN3M2RegClass.contains(Reg) ||
1143 RISCV::VRN4M1RegClass.contains(Reg) ||
1144 RISCV::VRN4M2RegClass.contains(Reg) ||
1145 RISCV::VRN5M1RegClass.contains(Reg) ||
1146 RISCV::VRN6M1RegClass.contains(Reg) ||
1147 RISCV::VRN7M1RegClass.contains(Reg) ||
1148 RISCV::VRN8M1RegClass.contains(Reg)) {
1149 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);
1150 assert(Reg && "Subregister does not exist");
1151 }
1152
1153 MCOp = MCOperand::createReg(Reg);
1154 break;
1155 }
1157 MCOp = MCOperand::createImm(MO.getImm());
1158 break;
1159 }
1160 OutMI.addOperand(MCOp);
1161 }
1162
1163 // Unmasked pseudo instructions need to append dummy mask operand to
1164 // V instructions. All V instructions are modeled as the masked version.
1165 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());
1166 if (OutMI.getNumOperands() < OutMCID.getNumOperands()) {
1167 assert(OutMCID.operands()[OutMI.getNumOperands()].RegClass ==
1168 RISCV::VMV0RegClassID &&
1169 "Expected only mask operand to be missing");
1170 OutMI.addOperand(MCOperand::createReg(RISCV::NoRegister));
1171 }
1172
1173 assert(OutMI.getNumOperands() == OutMCID.getNumOperands());
1174 return true;
1175}
1176
1177bool RISCVAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {
1178 if (lowerRISCVVMachineInstrToMCInst(MI, OutMI, STI))
1179 return false;
1180
1181 OutMI.setOpcode(MI->getOpcode());
1182
1183 for (const MachineOperand &MO : MI->operands()) {
1184 MCOperand MCOp;
1185 if (lowerOperand(MO, MCOp))
1186 OutMI.addOperand(MCOp);
1187 }
1188
1189 switch (OutMI.getOpcode()) {
1190 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
1191 const Function &F = MI->getParent()->getParent()->getFunction();
1192 if (F.hasFnAttribute("patchable-function-entry")) {
1193 unsigned Num;
1194 if (F.getFnAttribute("patchable-function-entry")
1195 .getValueAsString()
1196 .getAsInteger(10, Num))
1197 return false;
1198 emitNops(Num);
1199 return true;
1200 }
1201 break;
1202 }
1203 }
1204 return false;
1205}
1206
1207void RISCVAsmPrinter::emitMachineConstantPoolValue(
1209 auto *RCPV = static_cast<RISCVConstantPoolValue *>(MCPV);
1210 MCSymbol *MCSym;
1211
1212 if (RCPV->isGlobalValue()) {
1213 auto *GV = RCPV->getGlobalValue();
1214 MCSym = getSymbol(GV);
1215 } else {
1216 assert(RCPV->isExtSymbol() && "unrecognized constant pool type");
1217 auto Sym = RCPV->getSymbol();
1218 MCSym = GetExternalSymbolSymbol(Sym);
1219 }
1220
1221 const MCExpr *Expr = MCSymbolRefExpr::create(MCSym, OutContext);
1222 uint64_t Size = getDataLayout().getTypeAllocSize(RCPV->getType());
1223 OutStreamer->emitValue(Expr, Size);
1224}
1225
1226char RISCVAsmPrinter::ID = 0;
1227
1228INITIALIZE_PASS(RISCVAsmPrinter, "riscv-asm-printer", "RISC-V Assembly Printer",
1229 false, false)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static MCDisassembler::DecodeStatus addOperand(MCInst &Inst, const MCOperand &Opnd)
This file implements a class to represent arbitrary precision integral constant values and operations...
MachineBasicBlock & MBB
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
#define LLVM_ABI
Definition: Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:132
uint64_t Size
Symbol * Sym
Definition: ELF_riscv.cpp:479
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
static GCMetadataPrinterRegistry::Add< OcamlGCMetadataPrinter > Y("ocaml", "ocaml 3.10-compatible collector")
#define P(N)
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:56
static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, const RISCVSubtarget *STI)
static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym, const AsmPrinter &AP)
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter()
raw_pwrite_stream & OS
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:480
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:167
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:90
virtual void emitInstruction(const MachineInstr *)
Targets should implement this to emit instructions.
Definition: AsmPrinter.h:629
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
Definition: AsmPrinter.cpp:433
virtual void emitStartOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the start of their fi...
Definition: AsmPrinter.h:605
virtual void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV)
virtual void emitEndOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the end of their file...
Definition: AsmPrinter.h:609
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition: AsmPrinter.h:100
bool runOnMachineFunction(MachineFunction &MF) override
Emit the specified function out to the OutStreamer.
Definition: AsmPrinter.h:452
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.
The address of a basic block.
Definition: Constants.h:899
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:343
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:212
Context object for machine code objects.
Definition: MCContext.h:83
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
MCInstBuilder & addReg(MCRegister Reg)
Add a new register operand.
Definition: MCInstBuilder.h:37
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:43
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:188
unsigned getNumOperands() const
Definition: MCInst.h:212
unsigned getOpcode() const
Definition: MCInst.h:202
void addOperand(const MCOperand Op)
Definition: MCInst.h:215
void setOpcode(unsigned Op)
Definition: MCInst.h:201
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:199
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
Definition: MCInstrDesc.h:238
ArrayRef< MCOperandInfo > operands() const
Definition: MCInstrDesc.h:240
int getOperandConstraint(unsigned OpNum, MCOI::OperandConstraint Constraint) const
Returns the value of the specified operand constraint if it is present.
Definition: MCInstrDesc.h:220
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:40
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:166
int64_t getImm() const
Definition: MCInst.h:84
static MCOperand createReg(MCRegister Reg)
Definition: MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:145
const MCExpr * getExpr() const
Definition: MCInst.h:118
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.cpp:743
Streaming machine code generation interface.
Definition: MCStreamer.h:220
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
Definition: MCStreamer.h:314
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
Definition: MCStreamer.cpp:178
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Definition: MCStreamer.cpp:395
MCTargetStreamer * getTargetStreamer()
Definition: MCStreamer.h:324
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.
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
FeatureBitset ToggleFeature(uint64_t FB)
Toggle a feature and return the re-computed feature bits.
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:190
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition: MCExpr.h:214
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:42
A single uniqued string.
Definition: Metadata.h:720
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
Abstract base class for all machine specific constantpool value subclasses.
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.
Definition: MachineInstr.h:72
A description of a memory reference used in the backend.
Flags getFlags() const
Return the raw flags of the source value,.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isImplicit() 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.
Root of the metadata hierarchy.
Definition: Metadata.h:63
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
This class represents success/failure for parsing-like operations that find it important to chain tog...
Pass interface - Implemented by all 'passes'.
Definition: Pass.h:99
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:85
MI-level patchpoint operands.
Definition: StackMaps.h:77
A RISCV-specific constant pool value.
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)
RISCVMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private RISCV-...
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)
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
bool empty() const
Definition: SmallVector.h:82
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:938
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1197
MI-level stackmap operands.
Definition: StackMaps.h:36
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given stackmap should emit.
Definition: StackMaps.h:51
LLVM_ABI void recordStatepoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a statepoint instruction.
Definition: StackMaps.cpp:560
LLVM_ABI void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
Definition: StackMaps.cpp:539
LLVM_ABI void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
Definition: StackMaps.cpp:529
MI-level Statepoint operands.
Definition: StackMaps.h:159
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
TargetInstrInfo - Interface to description of machine instruction set.
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:83
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS
Definition: ELF.h:1905
@ SHT_PROGBITS
Definition: ELF.h:1140
@ SHF_ALLOC
Definition: ELF.h:1240
@ SHF_GROUP
Definition: ELF.h:1262
@ SHF_EXECINSTR
Definition: ELF.h:1243
ABI getTargetABI(StringRef ABIName)
static bool hasRoundModeOp(uint64_t TSFlags)
static bool isTiedPseudo(uint64_t TSFlags)
static bool hasVLOp(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)
Reg
All possible values of the reg field in the ModR/M byte.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool errorToBool(Error Err)
Helper for converting an Error to a bool.
Definition: Error.h:1113
@ Offset
Definition: DWP.cpp:477
static const MachineMemOperand::Flags MONontemporalBit1
Target & getTheRISCV32Target()
static const MachineMemOperand::Flags MONontemporalBit0
Target & getTheRISCV64beTarget()
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition: Error.cpp:167
Target & getTheRISCV64Target()
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1886
const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures]
@ MCSA_Weak
.weak
Definition: MCDirectives.h:45
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
Definition: MCDirectives.h:23
@ MCSA_Hidden
.hidden (ELF)
Definition: MCDirectives.h:33
Target & getTheRISCV32beTarget()
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:856
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...
Used to provide key value pairs for feature and CPU bit flags.