1 //===-- RISCVAsmPrinter.cpp - RISC-V LLVM assembly writer -----------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains a printer that converts from our internal representation
10 // of machine-dependent LLVM code to the RISC-V assembly language.
12 //===----------------------------------------------------------------------===//
14 #include "MCTargetDesc/RISCVBaseInfo.h"
15 #include "MCTargetDesc/RISCVInstPrinter.h"
16 #include "MCTargetDesc/RISCVMCExpr.h"
17 #include "MCTargetDesc/RISCVMatInt.h"
18 #include "MCTargetDesc/RISCVTargetStreamer.h"
20 #include "RISCVMachineFunctionInfo.h"
21 #include "RISCVTargetMachine.h"
22 #include "TargetInfo/RISCVTargetInfo.h"
23 #include "llvm/ADT/APInt.h"
24 #include "llvm/ADT/Statistic.h"
25 #include "llvm/BinaryFormat/ELF.h"
26 #include "llvm/CodeGen/AsmPrinter.h"
27 #include "llvm/CodeGen/MachineConstantPool.h"
28 #include "llvm/CodeGen/MachineFunctionPass.h"
29 #include "llvm/CodeGen/MachineInstr.h"
30 #include "llvm/CodeGen/MachineModuleInfo.h"
31 #include "llvm/MC/MCAsmInfo.h"
32 #include "llvm/MC/MCContext.h"
33 #include "llvm/MC/MCInst.h"
34 #include "llvm/MC/MCInstBuilder.h"
35 #include "llvm/MC/MCObjectFileInfo.h"
36 #include "llvm/MC/MCSectionELF.h"
37 #include "llvm/MC/MCStreamer.h"
38 #include "llvm/MC/MCSymbol.h"
39 #include "llvm/MC/TargetRegistry.h"
40 #include "llvm/Support/raw_ostream.h"
41 #include "llvm/TargetParser/RISCVISAInfo.h"
42 #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h"
46 #define DEBUG_TYPE "asm-printer"
48 STATISTIC(RISCVNumInstrsCompressed
,
49 "Number of RISC-V Compressed instructions emitted");
52 extern const SubtargetFeatureKV RISCVFeatureKV
[RISCV::NumSubtargetFeatures
];
56 class RISCVAsmPrinter
: public AsmPrinter
{
57 const RISCVSubtarget
*STI
;
60 explicit RISCVAsmPrinter(TargetMachine
&TM
,
61 std::unique_ptr
<MCStreamer
> Streamer
)
62 : AsmPrinter(TM
, std::move(Streamer
)) {}
64 StringRef
getPassName() const override
{ return "RISC-V Assembly Printer"; }
66 void LowerSTACKMAP(MCStreamer
&OutStreamer
, StackMaps
&SM
,
67 const MachineInstr
&MI
);
69 void LowerPATCHPOINT(MCStreamer
&OutStreamer
, StackMaps
&SM
,
70 const MachineInstr
&MI
);
72 void LowerSTATEPOINT(MCStreamer
&OutStreamer
, StackMaps
&SM
,
73 const MachineInstr
&MI
);
75 bool runOnMachineFunction(MachineFunction
&MF
) override
;
77 void emitInstruction(const MachineInstr
*MI
) override
;
79 bool PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
80 const char *ExtraCode
, raw_ostream
&OS
) override
;
81 bool PrintAsmMemoryOperand(const MachineInstr
*MI
, unsigned OpNo
,
82 const char *ExtraCode
, raw_ostream
&OS
) override
;
84 // Returns whether Inst is compressed.
85 bool EmitToStreamer(MCStreamer
&S
, const MCInst
&Inst
);
86 bool emitPseudoExpansionLowering(MCStreamer
&OutStreamer
,
87 const MachineInstr
*MI
);
89 typedef std::tuple
<unsigned, uint32_t> HwasanMemaccessTuple
;
90 std::map
<HwasanMemaccessTuple
, MCSymbol
*> HwasanMemaccessSymbols
;
91 void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr
&MI
);
92 void LowerKCFI_CHECK(const MachineInstr
&MI
);
93 void EmitHwasanMemaccessSymbols(Module
&M
);
95 // Wrapper needed for tblgenned pseudo lowering.
96 bool lowerOperand(const MachineOperand
&MO
, MCOperand
&MCOp
) const;
98 void emitStartOfAsmFile(Module
&M
) override
;
99 void emitEndOfAsmFile(Module
&M
) override
;
101 void emitFunctionEntryLabel() override
;
102 bool emitDirectiveOptionArch();
105 void emitAttributes(const MCSubtargetInfo
&SubtargetInfo
);
107 void emitNTLHint(const MachineInstr
*MI
);
109 bool lowerToMCInst(const MachineInstr
*MI
, MCInst
&OutMI
);
113 void RISCVAsmPrinter::LowerSTACKMAP(MCStreamer
&OutStreamer
, StackMaps
&SM
,
114 const MachineInstr
&MI
) {
115 unsigned NOPBytes
= STI
->hasStdExtCOrZca() ? 2 : 4;
116 unsigned NumNOPBytes
= StackMapOpers(&MI
).getNumPatchBytes();
118 auto &Ctx
= OutStreamer
.getContext();
119 MCSymbol
*MILabel
= Ctx
.createTempSymbol();
120 OutStreamer
.emitLabel(MILabel
);
122 SM
.recordStackMap(*MILabel
, MI
);
123 assert(NumNOPBytes
% NOPBytes
== 0 &&
124 "Invalid number of NOP bytes requested!");
126 // Scan ahead to trim the shadow.
127 const MachineBasicBlock
&MBB
= *MI
.getParent();
128 MachineBasicBlock::const_iterator
MII(MI
);
130 while (NumNOPBytes
> 0) {
131 if (MII
== MBB
.end() || MII
->isCall() ||
132 MII
->getOpcode() == RISCV::DBG_VALUE
||
133 MII
->getOpcode() == TargetOpcode::PATCHPOINT
||
134 MII
->getOpcode() == TargetOpcode::STACKMAP
)
141 emitNops(NumNOPBytes
/ NOPBytes
);
144 // Lower a patchpoint of the form:
145 // [<def>], <id>, <numBytes>, <target>, <numArgs>
146 void RISCVAsmPrinter::LowerPATCHPOINT(MCStreamer
&OutStreamer
, StackMaps
&SM
,
147 const MachineInstr
&MI
) {
148 unsigned NOPBytes
= STI
->hasStdExtCOrZca() ? 2 : 4;
150 auto &Ctx
= OutStreamer
.getContext();
151 MCSymbol
*MILabel
= Ctx
.createTempSymbol();
152 OutStreamer
.emitLabel(MILabel
);
153 SM
.recordPatchPoint(*MILabel
, MI
);
155 PatchPointOpers
Opers(&MI
);
157 const MachineOperand
&CalleeMO
= Opers
.getCallTarget();
158 unsigned EncodedBytes
= 0;
160 if (CalleeMO
.isImm()) {
161 uint64_t CallTarget
= CalleeMO
.getImm();
163 assert((CallTarget
& 0xFFFF'FFFF'FFFF) == CallTarget
&&
164 "High 16 bits of call target should be zero.");
165 // Materialize the jump address:
166 SmallVector
<MCInst
, 8> Seq
;
167 RISCVMatInt::generateMCInstSeq(CallTarget
, *STI
, RISCV::X1
, Seq
);
168 for (MCInst
&Inst
: Seq
) {
169 bool Compressed
= EmitToStreamer(OutStreamer
, Inst
);
170 EncodedBytes
+= Compressed
? 2 : 4;
172 bool Compressed
= EmitToStreamer(OutStreamer
, MCInstBuilder(RISCV::JALR
)
176 EncodedBytes
+= Compressed
? 2 : 4;
178 } else if (CalleeMO
.isGlobal()) {
179 MCOperand CallTargetMCOp
;
180 lowerOperand(CalleeMO
, CallTargetMCOp
);
181 EmitToStreamer(OutStreamer
,
182 MCInstBuilder(RISCV::PseudoCALL
).addOperand(CallTargetMCOp
));
187 unsigned NumBytes
= Opers
.getNumPatchBytes();
188 assert(NumBytes
>= EncodedBytes
&&
189 "Patchpoint can't request size less than the length of a call.");
190 assert((NumBytes
- EncodedBytes
) % NOPBytes
== 0 &&
191 "Invalid number of NOP bytes requested!");
192 emitNops((NumBytes
- EncodedBytes
) / NOPBytes
);
195 void RISCVAsmPrinter::LowerSTATEPOINT(MCStreamer
&OutStreamer
, StackMaps
&SM
,
196 const MachineInstr
&MI
) {
197 unsigned NOPBytes
= STI
->hasStdExtCOrZca() ? 2 : 4;
199 StatepointOpers
SOpers(&MI
);
200 if (unsigned PatchBytes
= SOpers
.getNumPatchBytes()) {
201 assert(PatchBytes
% NOPBytes
== 0 &&
202 "Invalid number of NOP bytes requested!");
203 emitNops(PatchBytes
/ NOPBytes
);
205 // Lower call target and choose correct opcode
206 const MachineOperand
&CallTarget
= SOpers
.getCallTarget();
207 MCOperand CallTargetMCOp
;
208 switch (CallTarget
.getType()) {
209 case MachineOperand::MO_GlobalAddress
:
210 case MachineOperand::MO_ExternalSymbol
:
211 lowerOperand(CallTarget
, CallTargetMCOp
);
214 MCInstBuilder(RISCV::PseudoCALL
).addOperand(CallTargetMCOp
));
216 case MachineOperand::MO_Immediate
:
217 CallTargetMCOp
= MCOperand::createImm(CallTarget
.getImm());
218 EmitToStreamer(OutStreamer
, MCInstBuilder(RISCV::JAL
)
220 .addOperand(CallTargetMCOp
));
222 case MachineOperand::MO_Register
:
223 CallTargetMCOp
= MCOperand::createReg(CallTarget
.getReg());
224 EmitToStreamer(OutStreamer
, MCInstBuilder(RISCV::JALR
)
226 .addOperand(CallTargetMCOp
)
230 llvm_unreachable("Unsupported operand type in statepoint call target");
235 auto &Ctx
= OutStreamer
.getContext();
236 MCSymbol
*MILabel
= Ctx
.createTempSymbol();
237 OutStreamer
.emitLabel(MILabel
);
238 SM
.recordStatepoint(*MILabel
, MI
);
241 bool RISCVAsmPrinter::EmitToStreamer(MCStreamer
&S
, const MCInst
&Inst
) {
243 bool Res
= RISCVRVC::compress(CInst
, Inst
, *STI
);
245 ++RISCVNumInstrsCompressed
;
246 AsmPrinter::EmitToStreamer(*OutStreamer
, Res
? CInst
: Inst
);
250 // Simple pseudo-instructions have their lowering (with expansion to real
251 // instructions) auto-generated.
252 #include "RISCVGenMCPseudoLowering.inc"
254 // If the target supports Zihintntl and the instruction has a nontemporal
255 // MachineMemOperand, emit an NTLH hint instruction before it.
256 void RISCVAsmPrinter::emitNTLHint(const MachineInstr
*MI
) {
257 if (!STI
->hasStdExtZihintntl())
260 if (MI
->memoperands_empty())
263 MachineMemOperand
*MMO
= *(MI
->memoperands_begin());
264 if (!MMO
->isNonTemporal())
267 unsigned NontemporalMode
= 0;
268 if (MMO
->getFlags() & MONontemporalBit0
)
269 NontemporalMode
+= 0b1;
270 if (MMO
->getFlags() & MONontemporalBit1
)
271 NontemporalMode
+= 0b10;
274 if (STI
->hasStdExtCOrZca() && STI
->enableRVCHintInstrs())
275 Hint
.setOpcode(RISCV::C_ADD_HINT
);
277 Hint
.setOpcode(RISCV::ADD
);
279 Hint
.addOperand(MCOperand::createReg(RISCV::X0
));
280 Hint
.addOperand(MCOperand::createReg(RISCV::X0
));
281 Hint
.addOperand(MCOperand::createReg(RISCV::X2
+ NontemporalMode
));
283 EmitToStreamer(*OutStreamer
, Hint
);
286 void RISCVAsmPrinter::emitInstruction(const MachineInstr
*MI
) {
287 RISCV_MC::verifyInstructionPredicates(MI
->getOpcode(),
288 getSubtargetInfo().getFeatureBits());
292 // Do any auto-generated pseudo lowerings.
293 if (emitPseudoExpansionLowering(*OutStreamer
, MI
))
297 switch (MI
->getOpcode()) {
298 case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES
:
299 LowerHWASAN_CHECK_MEMACCESS(*MI
);
301 case RISCV::KCFI_CHECK
:
302 LowerKCFI_CHECK(*MI
);
304 case RISCV::PseudoRVVInitUndefM1
:
305 case RISCV::PseudoRVVInitUndefM2
:
306 case RISCV::PseudoRVVInitUndefM4
:
307 case RISCV::PseudoRVVInitUndefM8
:
309 case TargetOpcode::STACKMAP
:
310 return LowerSTACKMAP(*OutStreamer
, SM
, *MI
);
311 case TargetOpcode::PATCHPOINT
:
312 return LowerPATCHPOINT(*OutStreamer
, SM
, *MI
);
313 case TargetOpcode::STATEPOINT
:
314 return LowerSTATEPOINT(*OutStreamer
, SM
, *MI
);
318 if (!lowerToMCInst(MI
, OutInst
))
319 EmitToStreamer(*OutStreamer
, OutInst
);
322 bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr
*MI
, unsigned OpNo
,
323 const char *ExtraCode
, raw_ostream
&OS
) {
324 // First try the generic code, which knows about modifiers like 'c' and 'n'.
325 if (!AsmPrinter::PrintAsmOperand(MI
, OpNo
, ExtraCode
, OS
))
328 const MachineOperand
&MO
= MI
->getOperand(OpNo
);
329 if (ExtraCode
&& ExtraCode
[0]) {
330 if (ExtraCode
[1] != 0)
331 return true; // Unknown modifier.
333 switch (ExtraCode
[0]) {
335 return true; // Unknown modifier.
336 case 'z': // Print zero register if zero, regular printing otherwise.
337 if (MO
.isImm() && MO
.getImm() == 0) {
338 OS
<< RISCVInstPrinter::getRegisterName(RISCV::X0
);
342 case 'i': // Literal 'i' if operand is not a register.
349 switch (MO
.getType()) {
350 case MachineOperand::MO_Immediate
:
353 case MachineOperand::MO_Register
:
354 OS
<< RISCVInstPrinter::getRegisterName(MO
.getReg());
356 case MachineOperand::MO_GlobalAddress
:
357 PrintSymbolOperand(MO
, OS
);
359 case MachineOperand::MO_BlockAddress
: {
360 MCSymbol
*Sym
= GetBlockAddressSymbol(MO
.getBlockAddress());
371 bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr
*MI
,
373 const char *ExtraCode
,
376 return AsmPrinter::PrintAsmMemoryOperand(MI
, OpNo
, ExtraCode
, OS
);
378 const MachineOperand
&AddrReg
= MI
->getOperand(OpNo
);
379 assert(MI
->getNumOperands() > OpNo
+ 1 && "Expected additional operand");
380 const MachineOperand
&Offset
= MI
->getOperand(OpNo
+ 1);
381 // All memory operands should have a register and an immediate operand (see
382 // RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand).
383 if (!AddrReg
.isReg())
385 if (!Offset
.isImm() && !Offset
.isGlobal() && !Offset
.isBlockAddress() &&
386 !Offset
.isMCSymbol())
390 if (!lowerOperand(Offset
, MCO
))
395 else if (Offset
.isGlobal() || Offset
.isBlockAddress() || Offset
.isMCSymbol())
396 OS
<< *MCO
.getExpr();
397 OS
<< "(" << RISCVInstPrinter::getRegisterName(AddrReg
.getReg()) << ")";
401 bool RISCVAsmPrinter::emitDirectiveOptionArch() {
402 RISCVTargetStreamer
&RTS
=
403 static_cast<RISCVTargetStreamer
&>(*OutStreamer
->getTargetStreamer());
404 SmallVector
<RISCVOptionArchArg
> NeedEmitStdOptionArgs
;
405 const MCSubtargetInfo
&MCSTI
= *TM
.getMCSubtargetInfo();
406 for (const auto &Feature
: RISCVFeatureKV
) {
407 if (STI
->hasFeature(Feature
.Value
) == MCSTI
.hasFeature(Feature
.Value
))
410 if (!llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature
.Key
))
413 auto Delta
= STI
->hasFeature(Feature
.Value
) ? RISCVOptionArchArgType::Plus
414 : RISCVOptionArchArgType::Minus
;
415 NeedEmitStdOptionArgs
.emplace_back(Delta
, Feature
.Key
);
417 if (!NeedEmitStdOptionArgs
.empty()) {
418 RTS
.emitDirectiveOptionPush();
419 RTS
.emitDirectiveOptionArch(NeedEmitStdOptionArgs
);
426 bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction
&MF
) {
427 STI
= &MF
.getSubtarget
<RISCVSubtarget
>();
428 RISCVTargetStreamer
&RTS
=
429 static_cast<RISCVTargetStreamer
&>(*OutStreamer
->getTargetStreamer());
431 bool EmittedOptionArch
= emitDirectiveOptionArch();
433 SetupMachineFunction(MF
);
436 if (EmittedOptionArch
)
437 RTS
.emitDirectiveOptionPop();
441 void RISCVAsmPrinter::emitStartOfAsmFile(Module
&M
) {
442 RISCVTargetStreamer
&RTS
=
443 static_cast<RISCVTargetStreamer
&>(*OutStreamer
->getTargetStreamer());
444 if (const MDString
*ModuleTargetABI
=
445 dyn_cast_or_null
<MDString
>(M
.getModuleFlag("target-abi")))
446 RTS
.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI
->getString()));
448 MCSubtargetInfo SubtargetInfo
= *TM
.getMCSubtargetInfo();
450 // Use module flag to update feature bits.
451 if (auto *MD
= dyn_cast_or_null
<MDNode
>(M
.getModuleFlag("riscv-isa"))) {
452 for (auto &ISA
: MD
->operands()) {
453 if (auto *ISAString
= dyn_cast_or_null
<MDString
>(ISA
)) {
454 auto ParseResult
= llvm::RISCVISAInfo::parseArchString(
455 ISAString
->getString(), /*EnableExperimentalExtension=*/true,
456 /*ExperimentalExtensionVersionCheck=*/true);
457 if (!errorToBool(ParseResult
.takeError())) {
458 auto &ISAInfo
= *ParseResult
;
459 for (const auto &Feature
: RISCVFeatureKV
) {
460 if (ISAInfo
->hasExtension(Feature
.Key
) &&
461 !SubtargetInfo
.hasFeature(Feature
.Value
))
462 SubtargetInfo
.ToggleFeature(Feature
.Key
);
468 RTS
.setFlagsFromFeatures(SubtargetInfo
);
471 if (TM
.getTargetTriple().isOSBinFormatELF())
472 emitAttributes(SubtargetInfo
);
475 void RISCVAsmPrinter::emitEndOfAsmFile(Module
&M
) {
476 RISCVTargetStreamer
&RTS
=
477 static_cast<RISCVTargetStreamer
&>(*OutStreamer
->getTargetStreamer());
479 if (TM
.getTargetTriple().isOSBinFormatELF())
480 RTS
.finishAttributeSection();
481 EmitHwasanMemaccessSymbols(M
);
484 void RISCVAsmPrinter::emitAttributes(const MCSubtargetInfo
&SubtargetInfo
) {
485 RISCVTargetStreamer
&RTS
=
486 static_cast<RISCVTargetStreamer
&>(*OutStreamer
->getTargetStreamer());
487 // Use MCSubtargetInfo from TargetMachine. Individual functions may have
488 // attributes that differ from other functions in the module and we have no
489 // way to know which function is correct.
490 RTS
.emitTargetAttributes(SubtargetInfo
, /*EmitStackAlign*/ true);
493 void RISCVAsmPrinter::emitFunctionEntryLabel() {
494 const auto *RMFI
= MF
->getInfo
<RISCVMachineFunctionInfo
>();
495 if (RMFI
->isVectorCall()) {
497 static_cast<RISCVTargetStreamer
&>(*OutStreamer
->getTargetStreamer());
498 RTS
.emitDirectiveVariantCC(*CurrentFnSym
);
500 return AsmPrinter::emitFunctionEntryLabel();
503 // Force static initialization.
504 extern "C" LLVM_EXTERNAL_VISIBILITY
void LLVMInitializeRISCVAsmPrinter() {
505 RegisterAsmPrinter
<RISCVAsmPrinter
> X(getTheRISCV32Target());
506 RegisterAsmPrinter
<RISCVAsmPrinter
> Y(getTheRISCV64Target());
509 void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr
&MI
) {
510 Register Reg
= MI
.getOperand(0).getReg();
511 uint32_t AccessInfo
= MI
.getOperand(1).getImm();
513 HwasanMemaccessSymbols
[HwasanMemaccessTuple(Reg
, AccessInfo
)];
515 // FIXME: Make this work on non-ELF.
516 if (!TM
.getTargetTriple().isOSBinFormatELF())
517 report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF");
519 std::string SymName
= "__hwasan_check_x" + utostr(Reg
- RISCV::X0
) + "_" +
520 utostr(AccessInfo
) + "_short";
521 Sym
= OutContext
.getOrCreateSymbol(SymName
);
523 auto Res
= MCSymbolRefExpr::create(Sym
, MCSymbolRefExpr::VK_None
, OutContext
);
524 auto Expr
= RISCVMCExpr::create(Res
, RISCVMCExpr::VK_RISCV_CALL
, OutContext
);
526 EmitToStreamer(*OutStreamer
, MCInstBuilder(RISCV::PseudoCALL
).addExpr(Expr
));
529 void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr
&MI
) {
530 Register AddrReg
= MI
.getOperand(0).getReg();
531 assert(std::next(MI
.getIterator())->isCall() &&
532 "KCFI_CHECK not followed by a call instruction");
533 assert(std::next(MI
.getIterator())->getOperand(0).getReg() == AddrReg
&&
534 "KCFI_CHECK call target doesn't match call operand");
536 // Temporary registers for comparing the hashes. If a register is used
537 // for the call target, or reserved by the user, we can clobber another
538 // temporary register as the check is immediately followed by the
539 // call. The check defaults to X6/X7, but can fall back to X28-X31 if
541 unsigned ScratchRegs
[] = {RISCV::X6
, RISCV::X7
};
542 unsigned NextReg
= RISCV::X28
;
543 auto isRegAvailable
= [&](unsigned Reg
) {
544 return Reg
!= AddrReg
&& !STI
->isRegisterReservedByUser(Reg
);
546 for (auto &Reg
: ScratchRegs
) {
547 if (isRegAvailable(Reg
))
549 while (!isRegAvailable(NextReg
))
552 if (Reg
> RISCV::X31
)
553 report_fatal_error("Unable to find scratch registers for KCFI_CHECK");
556 if (AddrReg
== RISCV::X0
) {
557 // Checking X0 makes no sense. Instead of emitting a load, zero
559 EmitToStreamer(*OutStreamer
, MCInstBuilder(RISCV::ADDI
)
560 .addReg(ScratchRegs
[0])
564 // Adjust the offset for patchable-function-prefix. This assumes that
565 // patchable-function-prefix is the same for all functions.
566 int NopSize
= STI
->hasStdExtCOrZca() ? 2 : 4;
567 int64_t PrefixNops
= 0;
570 .getFnAttribute("patchable-function-prefix")
572 .getAsInteger(10, PrefixNops
);
574 // Load the target function type hash.
575 EmitToStreamer(*OutStreamer
, MCInstBuilder(RISCV::LW
)
576 .addReg(ScratchRegs
[0])
578 .addImm(-(PrefixNops
* NopSize
+ 4)));
581 // Load the expected 32-bit type hash.
582 const int64_t Type
= MI
.getOperand(1).getImm();
583 const int64_t Hi20
= ((Type
+ 0x800) >> 12) & 0xFFFFF;
584 const int64_t Lo12
= SignExtend64
<12>(Type
);
588 MCInstBuilder(RISCV::LUI
).addReg(ScratchRegs
[1]).addImm(Hi20
));
590 if (Lo12
|| Hi20
== 0) {
591 EmitToStreamer(*OutStreamer
,
592 MCInstBuilder((STI
->hasFeature(RISCV::Feature64Bit
) && Hi20
)
595 .addReg(ScratchRegs
[1])
596 .addReg(ScratchRegs
[1])
600 // Compare the hashes and trap if there's a mismatch.
601 MCSymbol
*Pass
= OutContext
.createTempSymbol();
602 EmitToStreamer(*OutStreamer
,
603 MCInstBuilder(RISCV::BEQ
)
604 .addReg(ScratchRegs
[0])
605 .addReg(ScratchRegs
[1])
606 .addExpr(MCSymbolRefExpr::create(Pass
, OutContext
)));
608 MCSymbol
*Trap
= OutContext
.createTempSymbol();
609 OutStreamer
->emitLabel(Trap
);
610 EmitToStreamer(*OutStreamer
, MCInstBuilder(RISCV::EBREAK
));
611 emitKCFITrapEntry(*MI
.getMF(), Trap
);
612 OutStreamer
->emitLabel(Pass
);
615 void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module
&M
) {
616 if (HwasanMemaccessSymbols
.empty())
619 assert(TM
.getTargetTriple().isOSBinFormatELF());
620 // Use MCSubtargetInfo from TargetMachine. Individual functions may have
621 // attributes that differ from other functions in the module and we have no
622 // way to know which function is correct.
623 const MCSubtargetInfo
&MCSTI
= *TM
.getMCSubtargetInfo();
625 MCSymbol
*HwasanTagMismatchV2Sym
=
626 OutContext
.getOrCreateSymbol("__hwasan_tag_mismatch_v2");
627 // Annotate symbol as one having incompatible calling convention, so
628 // run-time linkers can instead eagerly bind this function.
630 static_cast<RISCVTargetStreamer
&>(*OutStreamer
->getTargetStreamer());
631 RTS
.emitDirectiveVariantCC(*HwasanTagMismatchV2Sym
);
633 const MCSymbolRefExpr
*HwasanTagMismatchV2Ref
=
634 MCSymbolRefExpr::create(HwasanTagMismatchV2Sym
, OutContext
);
635 auto Expr
= RISCVMCExpr::create(HwasanTagMismatchV2Ref
,
636 RISCVMCExpr::VK_RISCV_CALL
, OutContext
);
638 for (auto &P
: HwasanMemaccessSymbols
) {
639 unsigned Reg
= std::get
<0>(P
.first
);
640 uint32_t AccessInfo
= std::get
<1>(P
.first
);
641 MCSymbol
*Sym
= P
.second
;
644 1 << ((AccessInfo
>> HWASanAccessInfo::AccessSizeShift
) & 0xf);
645 OutStreamer
->switchSection(OutContext
.getELFSection(
646 ".text.hot", ELF::SHT_PROGBITS
,
647 ELF::SHF_EXECINSTR
| ELF::SHF_ALLOC
| ELF::SHF_GROUP
, 0, Sym
->getName(),
650 OutStreamer
->emitSymbolAttribute(Sym
, MCSA_ELF_TypeFunction
);
651 OutStreamer
->emitSymbolAttribute(Sym
, MCSA_Weak
);
652 OutStreamer
->emitSymbolAttribute(Sym
, MCSA_Hidden
);
653 OutStreamer
->emitLabel(Sym
);
655 // Extract shadow offset from ptr
656 OutStreamer
->emitInstruction(
657 MCInstBuilder(RISCV::SLLI
).addReg(RISCV::X6
).addReg(Reg
).addImm(8),
659 OutStreamer
->emitInstruction(MCInstBuilder(RISCV::SRLI
)
664 // load shadow tag in X6, X5 contains shadow base
665 OutStreamer
->emitInstruction(MCInstBuilder(RISCV::ADD
)
670 OutStreamer
->emitInstruction(
671 MCInstBuilder(RISCV::LBU
).addReg(RISCV::X6
).addReg(RISCV::X6
).addImm(0),
673 // Extract tag from X5 and compare it with loaded tag from shadow
674 OutStreamer
->emitInstruction(
675 MCInstBuilder(RISCV::SRLI
).addReg(RISCV::X7
).addReg(Reg
).addImm(56),
677 MCSymbol
*HandleMismatchOrPartialSym
= OutContext
.createTempSymbol();
678 // X7 contains tag from memory, while X6 contains tag from the pointer
679 OutStreamer
->emitInstruction(
680 MCInstBuilder(RISCV::BNE
)
683 .addExpr(MCSymbolRefExpr::create(HandleMismatchOrPartialSym
,
686 MCSymbol
*ReturnSym
= OutContext
.createTempSymbol();
687 OutStreamer
->emitLabel(ReturnSym
);
688 OutStreamer
->emitInstruction(MCInstBuilder(RISCV::JALR
)
693 OutStreamer
->emitLabel(HandleMismatchOrPartialSym
);
695 OutStreamer
->emitInstruction(MCInstBuilder(RISCV::ADDI
)
700 MCSymbol
*HandleMismatchSym
= OutContext
.createTempSymbol();
701 OutStreamer
->emitInstruction(
702 MCInstBuilder(RISCV::BGEU
)
705 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym
, OutContext
)),
708 OutStreamer
->emitInstruction(
709 MCInstBuilder(RISCV::ANDI
).addReg(RISCV::X28
).addReg(Reg
).addImm(0xF),
713 OutStreamer
->emitInstruction(MCInstBuilder(RISCV::ADDI
)
718 OutStreamer
->emitInstruction(
719 MCInstBuilder(RISCV::BGE
)
722 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym
, OutContext
)),
725 OutStreamer
->emitInstruction(
726 MCInstBuilder(RISCV::ORI
).addReg(RISCV::X6
).addReg(Reg
).addImm(0xF),
728 OutStreamer
->emitInstruction(
729 MCInstBuilder(RISCV::LBU
).addReg(RISCV::X6
).addReg(RISCV::X6
).addImm(0),
731 OutStreamer
->emitInstruction(
732 MCInstBuilder(RISCV::BEQ
)
735 .addExpr(MCSymbolRefExpr::create(ReturnSym
, OutContext
)),
738 OutStreamer
->emitLabel(HandleMismatchSym
);
740 // | Previous stack frames... |
741 // +=================================+ <-- [SP + 256]
744 // | Stack frame space for x12 - x31.|
747 // +---------------------------------+ <-- [SP + 96]
748 // | Saved x11(arg1), as |
749 // | __hwasan_check_* clobbers it. |
750 // +---------------------------------+ <-- [SP + 88]
751 // | Saved x10(arg0), as |
752 // | __hwasan_check_* clobbers it. |
753 // +---------------------------------+ <-- [SP + 80]
755 // | Stack frame space for x9. |
756 // +---------------------------------+ <-- [SP + 72]
758 // | Saved x8(fp), as |
759 // | __hwasan_check_* clobbers it. |
760 // +---------------------------------+ <-- [SP + 64]
763 // | Stack frame space for x2 - x7. |
766 // +---------------------------------+ <-- [SP + 16]
767 // | Return address (x1) for caller |
768 // | of __hwasan_check_*. |
769 // +---------------------------------+ <-- [SP + 8]
770 // | Reserved place for x0, possibly |
771 // | junk, since we don't save it. |
772 // +---------------------------------+ <-- [x2 / SP]
775 OutStreamer
->emitInstruction(MCInstBuilder(RISCV::ADDI
)
781 // store x10(arg0) by new sp
782 OutStreamer
->emitInstruction(MCInstBuilder(RISCV::SD
)
787 // store x11(arg1) by new sp
788 OutStreamer
->emitInstruction(MCInstBuilder(RISCV::SD
)
794 // store x8(fp) by new sp
795 OutStreamer
->emitInstruction(
796 MCInstBuilder(RISCV::SD
).addReg(RISCV::X8
).addReg(RISCV::X2
).addImm(8 *
799 // store x1(ra) by new sp
800 OutStreamer
->emitInstruction(
801 MCInstBuilder(RISCV::SD
).addReg(RISCV::X1
).addReg(RISCV::X2
).addImm(1 *
804 if (Reg
!= RISCV::X10
)
805 OutStreamer
->emitInstruction(MCInstBuilder(RISCV::ADDI
)
810 OutStreamer
->emitInstruction(
811 MCInstBuilder(RISCV::ADDI
)
814 .addImm(AccessInfo
& HWASanAccessInfo::RuntimeMask
),
817 OutStreamer
->emitInstruction(MCInstBuilder(RISCV::PseudoCALL
).addExpr(Expr
),
822 static MCOperand
lowerSymbolOperand(const MachineOperand
&MO
, MCSymbol
*Sym
,
823 const AsmPrinter
&AP
) {
824 MCContext
&Ctx
= AP
.OutContext
;
825 RISCVMCExpr::VariantKind Kind
;
827 switch (MO
.getTargetFlags()) {
829 llvm_unreachable("Unknown target flag on GV operand");
830 case RISCVII::MO_None
:
831 Kind
= RISCVMCExpr::VK_RISCV_None
;
833 case RISCVII::MO_CALL
:
834 Kind
= RISCVMCExpr::VK_RISCV_CALL_PLT
;
837 Kind
= RISCVMCExpr::VK_RISCV_LO
;
840 Kind
= RISCVMCExpr::VK_RISCV_HI
;
842 case RISCVII::MO_PCREL_LO
:
843 Kind
= RISCVMCExpr::VK_RISCV_PCREL_LO
;
845 case RISCVII::MO_PCREL_HI
:
846 Kind
= RISCVMCExpr::VK_RISCV_PCREL_HI
;
848 case RISCVII::MO_GOT_HI
:
849 Kind
= RISCVMCExpr::VK_RISCV_GOT_HI
;
851 case RISCVII::MO_TPREL_LO
:
852 Kind
= RISCVMCExpr::VK_RISCV_TPREL_LO
;
854 case RISCVII::MO_TPREL_HI
:
855 Kind
= RISCVMCExpr::VK_RISCV_TPREL_HI
;
857 case RISCVII::MO_TPREL_ADD
:
858 Kind
= RISCVMCExpr::VK_RISCV_TPREL_ADD
;
860 case RISCVII::MO_TLS_GOT_HI
:
861 Kind
= RISCVMCExpr::VK_RISCV_TLS_GOT_HI
;
863 case RISCVII::MO_TLS_GD_HI
:
864 Kind
= RISCVMCExpr::VK_RISCV_TLS_GD_HI
;
866 case RISCVII::MO_TLSDESC_HI
:
867 Kind
= RISCVMCExpr::VK_RISCV_TLSDESC_HI
;
869 case RISCVII::MO_TLSDESC_LOAD_LO
:
870 Kind
= RISCVMCExpr::VK_RISCV_TLSDESC_LOAD_LO
;
872 case RISCVII::MO_TLSDESC_ADD_LO
:
873 Kind
= RISCVMCExpr::VK_RISCV_TLSDESC_ADD_LO
;
875 case RISCVII::MO_TLSDESC_CALL
:
876 Kind
= RISCVMCExpr::VK_RISCV_TLSDESC_CALL
;
881 MCSymbolRefExpr::create(Sym
, MCSymbolRefExpr::VK_None
, Ctx
);
883 if (!MO
.isJTI() && !MO
.isMBB() && MO
.getOffset())
884 ME
= MCBinaryExpr::createAdd(
885 ME
, MCConstantExpr::create(MO
.getOffset(), Ctx
), Ctx
);
887 if (Kind
!= RISCVMCExpr::VK_RISCV_None
)
888 ME
= RISCVMCExpr::create(ME
, Kind
, Ctx
);
889 return MCOperand::createExpr(ME
);
892 bool RISCVAsmPrinter::lowerOperand(const MachineOperand
&MO
,
893 MCOperand
&MCOp
) const {
894 switch (MO
.getType()) {
896 report_fatal_error("lowerOperand: unknown operand type");
897 case MachineOperand::MO_Register
:
898 // Ignore all implicit register operands.
901 MCOp
= MCOperand::createReg(MO
.getReg());
903 case MachineOperand::MO_RegisterMask
:
904 // Regmasks are like implicit defs.
906 case MachineOperand::MO_Immediate
:
907 MCOp
= MCOperand::createImm(MO
.getImm());
909 case MachineOperand::MO_MachineBasicBlock
:
910 MCOp
= lowerSymbolOperand(MO
, MO
.getMBB()->getSymbol(), *this);
912 case MachineOperand::MO_GlobalAddress
:
913 MCOp
= lowerSymbolOperand(MO
, getSymbolPreferLocal(*MO
.getGlobal()), *this);
915 case MachineOperand::MO_BlockAddress
:
916 MCOp
= lowerSymbolOperand(MO
, GetBlockAddressSymbol(MO
.getBlockAddress()),
919 case MachineOperand::MO_ExternalSymbol
:
920 MCOp
= lowerSymbolOperand(MO
, GetExternalSymbolSymbol(MO
.getSymbolName()),
923 case MachineOperand::MO_ConstantPoolIndex
:
924 MCOp
= lowerSymbolOperand(MO
, GetCPISymbol(MO
.getIndex()), *this);
926 case MachineOperand::MO_JumpTableIndex
:
927 MCOp
= lowerSymbolOperand(MO
, GetJTISymbol(MO
.getIndex()), *this);
929 case MachineOperand::MO_MCSymbol
:
930 MCOp
= lowerSymbolOperand(MO
, MO
.getMCSymbol(), *this);
936 static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr
*MI
,
938 const RISCVVPseudosTable::PseudoInfo
*RVV
=
939 RISCVVPseudosTable::getPseudoInfo(MI
->getOpcode());
943 OutMI
.setOpcode(RVV
->BaseInstr
);
945 const MachineBasicBlock
*MBB
= MI
->getParent();
946 assert(MBB
&& "MI expected to be in a basic block");
947 const MachineFunction
*MF
= MBB
->getParent();
948 assert(MF
&& "MBB expected to be in a machine function");
950 const RISCVSubtarget
&Subtarget
= MF
->getSubtarget
<RISCVSubtarget
>();
951 const TargetInstrInfo
*TII
= Subtarget
.getInstrInfo();
952 const TargetRegisterInfo
*TRI
= Subtarget
.getRegisterInfo();
953 assert(TRI
&& "TargetRegisterInfo expected");
955 const MCInstrDesc
&MCID
= MI
->getDesc();
956 uint64_t TSFlags
= MCID
.TSFlags
;
957 unsigned NumOps
= MI
->getNumExplicitOperands();
959 // Skip policy, SEW, VL, VXRM/FRM operands which are the last operands if
961 if (RISCVII::hasVecPolicyOp(TSFlags
))
963 if (RISCVII::hasSEWOp(TSFlags
))
965 if (RISCVII::hasVLOp(TSFlags
))
967 if (RISCVII::hasRoundModeOp(TSFlags
))
970 bool hasVLOutput
= RISCV::isFaultFirstLoad(*MI
);
971 for (unsigned OpNo
= 0; OpNo
!= NumOps
; ++OpNo
) {
972 const MachineOperand
&MO
= MI
->getOperand(OpNo
);
973 // Skip vl ouput. It should be the second output.
974 if (hasVLOutput
&& OpNo
== 1)
977 // Skip merge op. It should be the first operand after the defs.
978 if (OpNo
== MI
->getNumExplicitDefs() && MO
.isReg() && MO
.isTied()) {
979 assert(MCID
.getOperandConstraint(OpNo
, MCOI::TIED_TO
) == 0 &&
980 "Expected tied to first def.");
981 const MCInstrDesc
&OutMCID
= TII
->get(OutMI
.getOpcode());
982 // Skip if the next operand in OutMI is not supposed to be tied. Unless it
983 // is a _TIED instruction.
984 if (OutMCID
.getOperandConstraint(OutMI
.getNumOperands(), MCOI::TIED_TO
) <
986 !RISCVII::isTiedPseudo(TSFlags
))
991 switch (MO
.getType()) {
993 llvm_unreachable("Unknown operand type");
994 case MachineOperand::MO_Register
: {
995 Register Reg
= MO
.getReg();
997 if (RISCV::VRM2RegClass
.contains(Reg
) ||
998 RISCV::VRM4RegClass
.contains(Reg
) ||
999 RISCV::VRM8RegClass
.contains(Reg
)) {
1000 Reg
= TRI
->getSubReg(Reg
, RISCV::sub_vrm1_0
);
1001 assert(Reg
&& "Subregister does not exist");
1002 } else if (RISCV::FPR16RegClass
.contains(Reg
)) {
1004 TRI
->getMatchingSuperReg(Reg
, RISCV::sub_16
, &RISCV::FPR32RegClass
);
1005 assert(Reg
&& "Subregister does not exist");
1006 } else if (RISCV::FPR64RegClass
.contains(Reg
)) {
1007 Reg
= TRI
->getSubReg(Reg
, RISCV::sub_32
);
1008 assert(Reg
&& "Superregister does not exist");
1009 } else if (RISCV::VRN2M1RegClass
.contains(Reg
) ||
1010 RISCV::VRN2M2RegClass
.contains(Reg
) ||
1011 RISCV::VRN2M4RegClass
.contains(Reg
) ||
1012 RISCV::VRN3M1RegClass
.contains(Reg
) ||
1013 RISCV::VRN3M2RegClass
.contains(Reg
) ||
1014 RISCV::VRN4M1RegClass
.contains(Reg
) ||
1015 RISCV::VRN4M2RegClass
.contains(Reg
) ||
1016 RISCV::VRN5M1RegClass
.contains(Reg
) ||
1017 RISCV::VRN6M1RegClass
.contains(Reg
) ||
1018 RISCV::VRN7M1RegClass
.contains(Reg
) ||
1019 RISCV::VRN8M1RegClass
.contains(Reg
)) {
1020 Reg
= TRI
->getSubReg(Reg
, RISCV::sub_vrm1_0
);
1021 assert(Reg
&& "Subregister does not exist");
1024 MCOp
= MCOperand::createReg(Reg
);
1027 case MachineOperand::MO_Immediate
:
1028 MCOp
= MCOperand::createImm(MO
.getImm());
1031 OutMI
.addOperand(MCOp
);
1034 // Unmasked pseudo instructions need to append dummy mask operand to
1035 // V instructions. All V instructions are modeled as the masked version.
1036 const MCInstrDesc
&OutMCID
= TII
->get(OutMI
.getOpcode());
1037 if (OutMI
.getNumOperands() < OutMCID
.getNumOperands()) {
1038 assert(OutMCID
.operands()[OutMI
.getNumOperands()].RegClass
==
1039 RISCV::VMV0RegClassID
&&
1040 "Expected only mask operand to be missing");
1041 OutMI
.addOperand(MCOperand::createReg(RISCV::NoRegister
));
1044 assert(OutMI
.getNumOperands() == OutMCID
.getNumOperands());
1048 bool RISCVAsmPrinter::lowerToMCInst(const MachineInstr
*MI
, MCInst
&OutMI
) {
1049 if (lowerRISCVVMachineInstrToMCInst(MI
, OutMI
))
1052 OutMI
.setOpcode(MI
->getOpcode());
1054 for (const MachineOperand
&MO
: MI
->operands()) {
1056 if (lowerOperand(MO
, MCOp
))
1057 OutMI
.addOperand(MCOp
);
1060 switch (OutMI
.getOpcode()) {
1061 case TargetOpcode::PATCHABLE_FUNCTION_ENTER
: {
1062 const Function
&F
= MI
->getParent()->getParent()->getFunction();
1063 if (F
.hasFnAttribute("patchable-function-entry")) {
1065 if (F
.getFnAttribute("patchable-function-entry")
1067 .getAsInteger(10, Num
))