1224 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains a printer that converts from our internal representation10// of machine-dependent LLVM code to the RISC-V assembly language.11//12//===----------------------------------------------------------------------===//13 14#include "MCTargetDesc/RISCVBaseInfo.h"15#include "MCTargetDesc/RISCVInstPrinter.h"16#include "MCTargetDesc/RISCVMCAsmInfo.h"17#include "MCTargetDesc/RISCVMatInt.h"18#include "MCTargetDesc/RISCVTargetStreamer.h"19#include "RISCV.h"20#include "RISCVConstantPoolValue.h"21#include "RISCVMachineFunctionInfo.h"22#include "RISCVRegisterInfo.h"23#include "TargetInfo/RISCVTargetInfo.h"24#include "llvm/ADT/APInt.h"25#include "llvm/ADT/Statistic.h"26#include "llvm/BinaryFormat/ELF.h"27#include "llvm/CodeGen/AsmPrinter.h"28#include "llvm/CodeGen/MachineConstantPool.h"29#include "llvm/CodeGen/MachineInstr.h"30#include "llvm/CodeGen/MachineModuleInfo.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"35#include "llvm/MC/MCInstBuilder.h"36#include "llvm/MC/MCObjectFileInfo.h"37#include "llvm/MC/MCSectionELF.h"38#include "llvm/MC/MCStreamer.h"39#include "llvm/MC/MCSymbol.h"40#include "llvm/MC/TargetRegistry.h"41#include "llvm/Support/Compiler.h"42#include "llvm/Support/raw_ostream.h"43#include "llvm/TargetParser/RISCVISAInfo.h"44#include "llvm/Transforms/Instrumentation/HWAddressSanitizer.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 llvm56 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 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 // 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 Support124 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,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();148 MachineBasicBlock::const_iterator MII(MI);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:186 SmallVector<MCInst, 8> Seq;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 opcode226 const MachineOperand &CallTarget = SOpers.getCallTarget();227 MCOperand CallTargetMCOp;228 switch (CallTarget.getType()) {229 case MachineOperand::MO_GlobalAddress:230 case MachineOperand::MO_ExternalSymbol:231 lowerOperand(CallTarget, CallTargetMCOp);232 EmitToStreamer(233 OutStreamer,234 MCInstBuilder(RISCV::PseudoCALL).addOperand(CallTargetMCOp));235 break;236 case MachineOperand::MO_Immediate:237 CallTargetMCOp = MCOperand::createImm(CallTarget.getImm());238 EmitToStreamer(OutStreamer, MCInstBuilder(RISCV::JAL)239 .addReg(RISCV::X1)240 .addOperand(CallTargetMCOp));241 break;242 case MachineOperand::MO_Register: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 real272// instructions) auto-generated.273#include "RISCVGenMCPseudoLowering.inc"274 275// If the target supports Zihintntl and the instruction has a nontemporal276// 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 else298 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 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 // First try the generic code, which knows about modifiers like 'c' and 'n'.362 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS))363 return false;364 365 const MachineOperand &MO = MI->getOperand(OpNo);366 if (ExtraCode && ExtraCode[0]) {367 if (ExtraCode[1] != 0)368 return true; // Unknown modifier.369 370 switch (ExtraCode[0]) {371 default:372 return true; // Unknown modifier.373 case 'z': // Print zero register if zero, regular printing otherwise.374 if (MO.isImm() && MO.getImm() == 0) {375 OS << RISCVInstPrinter::getRegisterName(RISCV::X0);376 return false;377 }378 break;379 case 'i': // Literal 'i' if operand is not a register.380 if (!MO.isReg())381 OS << 'i';382 return false;383 case 'N': // Print the register encoding as an integer (0-31)384 if (!MO.isReg())385 return true;386 387 const RISCVRegisterInfo *TRI = STI->getRegisterInfo();388 OS << TRI->getEncodingValue(MO.getReg());389 return false;390 }391 }392 393 switch (MO.getType()) {394 case MachineOperand::MO_Immediate:395 OS << MO.getImm();396 return false;397 case MachineOperand::MO_Register:398 OS << RISCVInstPrinter::getRegisterName(MO.getReg());399 return false;400 case MachineOperand::MO_GlobalAddress:401 PrintSymbolOperand(MO, OS);402 return false;403 case MachineOperand::MO_BlockAddress: {404 MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress());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)420 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS);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 // All memory operands should have a register and an immediate operand (see426 // RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand).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 437 if (Offset.isImm())438 OS << MCO.getImm();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()) {445 const BlockAddress *BA = Offset.getBlockAddress();446 MCSymbol *Sym = GetBlockAddressSymbol(BA);447 MMI->getContext().registerInlineAsmLabel(Sym);448 }449 450 OS << "(" << RISCVInstPrinter::getRegisterName(AddrReg.getReg()) << ")";451 return false;452}453 454bool RISCVAsmPrinter::emitDirectiveOptionArch() {455 RISCVTargetStreamer &RTS =456 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());457 SmallVector<RISCVOptionArchArg> NeedEmitStdOptionArgs;458 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();459 for (const auto &Feature : RISCVFeatureKV) {460 if (STI->hasFeature(Feature.Value) == MCSTI.hasFeature(Feature.Value))461 continue;462 463 if (!llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key))464 continue;465 466 auto Delta = STI->hasFeature(Feature.Value) ? RISCVOptionArchArgType::Plus467 : RISCVOptionArchArgType::Minus;468 NeedEmitStdOptionArgs.emplace_back(Delta, Feature.Key);469 }470 if (!NeedEmitStdOptionArgs.empty()) {471 RTS.emitDirectiveOptionPush();472 RTS.emitDirectiveOptionArch(NeedEmitStdOptionArgs);473 return true;474 }475 476 return false;477}478 479bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) {480 STI = &MF.getSubtarget<RISCVSubtarget>();481 RISCVTargetStreamer &RTS =482 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());483 484 bool EmittedOptionArch = emitDirectiveOptionArch();485 486 SetupMachineFunction(MF);487 emitFunctionBody();488 489 // Emit the XRay table490 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 // We want to emit the jump instruction and the nops constituting the sled.511 // The format is as follows:512 // .Lxray_sled_N513 // ALIGN514 // J .tmpN515 // 21 or 33 C.NOP instructions516 // .tmpN517 518 // The following variable holds the count of the number of NOPs to be patched519 // in for XRay instrumentation during compilation.520 // Note that RV64 and RV32 each has a sled of 68 and 44 bytes, respectively.521 // Assuming we're using JAL to jump to .tmpN, then we only need522 // (68 - 4)/2 = 32 NOPs for RV64 and (44 - 4)/2 = 20 for RV32. However, there523 // is a chance that we'll use C.JAL instead, so an additional NOP is needed.524 const uint8_t NoopsInSledCount = STI->is64Bit() ? 33 : 21;525 526 OutStreamer->emitCodeAlignment(Align(4), STI);527 auto CurSled = OutContext.createTempSymbol("xray_sled_", true);528 OutStreamer->emitLabel(CurSled);529 auto Target = OutContext.createTempSymbol();530 531 const MCExpr *TargetExpr = MCSymbolRefExpr::create(Target, OutContext);532 533 // Emit "J bytes" instruction, which jumps over the nop sled to the actual534 // start of function.535 EmitToStreamer(536 *OutStreamer,537 MCInstBuilder(RISCV::JAL).addReg(RISCV::X0).addExpr(TargetExpr));538 539 // Emit NOP instructions540 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 546 OutStreamer->emitLabel(Target);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 =554 dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi")))555 RTS.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI->getString()));556 557 MCSubtargetInfo SubtargetInfo = *TM.getMCSubtargetInfo();558 559 // Use module flag to update feature bits.560 if (auto *MD = dyn_cast_or_null<MDNode>(M.getModuleFlag("riscv-isa"))) {561 for (auto &ISA : MD->operands()) {562 if (auto *ISAString = dyn_cast_or_null<MDString>(ISA)) {563 auto ParseResult = llvm::RISCVISAInfo::parseArchString(564 ISAString->getString(), /*EnableExperimentalExtension=*/true,565 /*ExperimentalExtensionVersionCheck=*/true);566 if (!errorToBool(ParseResult.takeError())) {567 auto &ISAInfo = *ParseResult;568 for (const auto &Feature : RISCVFeatureKV) {569 if (ISAInfo->hasExtension(Feature.Key) &&570 !SubtargetInfo.hasFeature(Feature.Value))571 SubtargetInfo.ToggleFeature(Feature.Key);572 }573 }574 }575 }576 577 RTS.setFlagsFromFeatures(SubtargetInfo);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()) {589 RTS.finishAttributeSection();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 // Use MCSubtargetInfo from TargetMachine. Individual functions may have599 // attributes that differ from other functions in the module and we have no600 // way to know which function is correct.601 RTS.emitTargetAttributes(SubtargetInfo, /*EmitStackAlign*/ true);602}603 604void RISCVAsmPrinter::emitFunctionEntryLabel() {605 const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>();606 if (RMFI->isVectorCall()) {607 auto &RTS =608 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());609 RTS.emitDirectiveVariantCC(*CurrentFnSym);610 }611 return AsmPrinter::emitFunctionEntryLabel();612}613 614// Force static initialization.615extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void616LLVMInitializeRISCVAsmPrinter() {617 RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target());618 RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target());619 RegisterAsmPrinter<RISCVAsmPrinter> A(getTheRISCV32beTarget());620 RegisterAsmPrinter<RISCVAsmPrinter> B(getTheRISCV64beTarget());621}622 623void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) {624 Register Reg = MI.getOperand(0).getReg();625 uint32_t AccessInfo = MI.getOperand(1).getImm();626 MCSymbol *&Sym =627 HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)];628 if (!Sym) {629 // FIXME: Make this work on non-ELF.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 }637 auto Res = MCSymbolRefExpr::create(Sym, OutContext);638 auto Expr = MCSpecifierExpr::create(Res, ELF::R_RISCV_CALL_PLT, OutContext);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 // Temporary registers for comparing the hashes. If a register is used651 // for the call target, or reserved by the user, we can clobber another652 // temporary register as the check is immediately followed by the653 // call. The check defaults to X6/X7, but can fall back to X28-X31 if654 // needed.655 unsigned ScratchRegs[] = {RISCV::X6, RISCV::X7};656 unsigned NextReg = RISCV::X28;657 auto isRegAvailable = [&](unsigned Reg) {658 return Reg != AddrReg && !STI->isRegisterReservedByUser(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 // Checking X0 makes no sense. Instead of emitting a load, zero672 // ScratchRegs[0].673 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::ADDI)674 .addReg(ScratchRegs[0])675 .addReg(RISCV::X0)676 .addImm(0));677 } else {678 // Adjust the offset for patchable-function-prefix. This assumes that679 // patchable-function-prefix is the same for all functions.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 // Load the target function type hash.689 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW)690 .addReg(ScratchRegs[0])691 .addReg(AddrReg)692 .addImm(-(PrefixNops * NopSize + 4)));693 }694 695 // Load the expected 32-bit type hash.696 const int64_t Type = MI.getOperand(1).getImm();697 const int64_t Hi20 = ((Type + 0x800) >> 12) & 0xFFFFF;698 const int64_t Lo12 = SignExtend64<12>(Type);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::ADDIW708 : RISCV::ADDI)709 .addReg(ScratchRegs[1])710 .addReg(ScratchRegs[1])711 .addImm(Lo12));712 }713 714 // Compare the hashes and trap if there's a mismatch.715 MCSymbol *Pass = OutContext.createTempSymbol();716 EmitToStreamer(*OutStreamer,717 MCInstBuilder(RISCV::BEQ)718 .addReg(ScratchRegs[0])719 .addReg(ScratchRegs[1])720 .addExpr(MCSymbolRefExpr::create(Pass, OutContext)));721 722 MCSymbol *Trap = OutContext.createTempSymbol();723 OutStreamer->emitLabel(Trap);724 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::EBREAK));725 emitKCFITrapEntry(*MI.getMF(), Trap);726 OutStreamer->emitLabel(Pass);727}728 729void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) {730 if (HwasanMemaccessSymbols.empty())731 return;732 733 assert(TM.getTargetTriple().isOSBinFormatELF());734 // Use MCSubtargetInfo from TargetMachine. Individual functions may have735 // attributes that differ from other functions in the module and we have no736 // way to know which function is correct.737 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo();738 739 MCSymbol *HwasanTagMismatchV2Sym =740 OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2");741 // Annotate symbol as one having incompatible calling convention, so742 // run-time linkers can instead eagerly bind this function.743 auto &RTS =744 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());745 RTS.emitDirectiveVariantCC(*HwasanTagMismatchV2Sym);746 747 const MCSymbolRefExpr *HwasanTagMismatchV2Ref =748 MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext);749 auto Expr = MCSpecifierExpr::create(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);755 MCSymbol *Sym = P.second;756 757 unsigned Size =758 1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf);759 OutStreamer->switchSection(OutContext.getELFSection(760 ".text.hot", ELF::SHT_PROGBITS,761 ELF::SHF_EXECINSTR | ELF::SHF_ALLOC | ELF::SHF_GROUP, 0, Sym->getName(),762 /*IsComdat=*/true));763 764 OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);765 OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak);766 OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden);767 OutStreamer->emitLabel(Sym);768 769 // Extract shadow offset from ptr770 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 // load shadow tag in X6, X5 contains shadow base781 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 // Extract tag from pointer and compare it with loaded tag from shadow792 EmitToStreamer(793 *OutStreamer,794 MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(Reg).addImm(56),795 MCSTI);796 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol();797 // X7 contains tag from the pointer, while X6 contains tag from memory798 EmitToStreamer(*OutStreamer,799 MCInstBuilder(RISCV::BNE)800 .addReg(RISCV::X7)801 .addReg(RISCV::X6)802 .addExpr(MCSymbolRefExpr::create(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)827 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),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)847 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)),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)862 .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)),863 MCSTI);864 865 OutStreamer->emitLabel(HandleMismatchSym);866 867 // | Previous stack frames... |868 // +=================================+ <-- [SP + 256]869 // | ... |870 // | |871 // | Stack frame space for x12 - x31.|872 // | |873 // | ... |874 // +---------------------------------+ <-- [SP + 96]875 // | Saved x11(arg1), as |876 // | __hwasan_check_* clobbers it. |877 // +---------------------------------+ <-- [SP + 88]878 // | Saved x10(arg0), as |879 // | __hwasan_check_* clobbers it. |880 // +---------------------------------+ <-- [SP + 80]881 // | |882 // | Stack frame space for x9. |883 // +---------------------------------+ <-- [SP + 72]884 // | |885 // | Saved x8(fp), as |886 // | __hwasan_check_* clobbers it. |887 // +---------------------------------+ <-- [SP + 64]888 // | ... |889 // | |890 // | Stack frame space for x2 - x7. |891 // | |892 // | ... |893 // +---------------------------------+ <-- [SP + 16]894 // | Return address (x1) for caller |895 // | of __hwasan_check_*. |896 // +---------------------------------+ <-- [SP + 8]897 // | Reserved place for x0, possibly |898 // | junk, since we don't save it. |899 // +---------------------------------+ <-- [x2 / SP]900 901 // Adjust sp902 EmitToStreamer(*OutStreamer,903 MCInstBuilder(RISCV::ADDI)904 .addReg(RISCV::X2)905 .addReg(RISCV::X2)906 .addImm(-256),907 MCSTI);908 909 // store x10(arg0) by new sp910 EmitToStreamer(*OutStreamer,911 MCInstBuilder(RISCV::SD)912 .addReg(RISCV::X10)913 .addReg(RISCV::X2)914 .addImm(8 * 10),915 MCSTI);916 // store x11(arg1) by new sp917 EmitToStreamer(*OutStreamer,918 MCInstBuilder(RISCV::SD)919 .addReg(RISCV::X11)920 .addReg(RISCV::X2)921 .addImm(8 * 11),922 MCSTI);923 924 // store x8(fp) by new sp925 EmitToStreamer(926 *OutStreamer,927 MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 *928 8),929 MCSTI);930 // store x1(ra) by new sp931 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)945 .addImm(AccessInfo & HWASanAccessInfo::RuntimeMask),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");955 Flag && !mdconst::extract<ConstantInt>(Flag)->isZero()) {956 RISCVTargetStreamer &RTS =957 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer());958 RTS.emitNoteGnuPropertySection(ELF::GNU_PROPERTY_RISCV_FEATURE_1_CFI_SS);959 }960}961 962static MCOperand lowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym,963 const AsmPrinter &AP) {964 MCContext &Ctx = AP.OutContext;965 RISCV::Specifier Kind;966 967 switch (MO.getTargetFlags()) {968 default:969 llvm_unreachable("Unknown target flag on GV operand");970 case RISCVII::MO_None:971 Kind = RISCV::S_None;972 break;973 case RISCVII::MO_CALL:974 Kind = ELF::R_RISCV_CALL_PLT;975 break;976 case RISCVII::MO_LO:977 Kind = RISCV::S_LO;978 break;979 case RISCVII::MO_HI:980 Kind = ELF::R_RISCV_HI20;981 break;982 case RISCVII::MO_PCREL_LO:983 Kind = RISCV::S_PCREL_LO;984 break;985 case RISCVII::MO_PCREL_HI:986 Kind = ELF::R_RISCV_PCREL_HI20;987 break;988 case RISCVII::MO_GOT_HI:989 Kind = ELF::R_RISCV_GOT_HI20;990 break;991 case RISCVII::MO_TPREL_LO:992 Kind = RISCV::S_TPREL_LO;993 break;994 case RISCVII::MO_TPREL_HI:995 Kind = ELF::R_RISCV_TPREL_HI20;996 break;997 case RISCVII::MO_TPREL_ADD:998 Kind = ELF::R_RISCV_TPREL_ADD;999 break;1000 case RISCVII::MO_TLS_GOT_HI:1001 Kind = ELF::R_RISCV_TLS_GOT_HI20;1002 break;1003 case RISCVII::MO_TLS_GD_HI:1004 Kind = ELF::R_RISCV_TLS_GD_HI20;1005 break;1006 case RISCVII::MO_TLSDESC_HI:1007 Kind = ELF::R_RISCV_TLSDESC_HI20;1008 break;1009 case RISCVII::MO_TLSDESC_LOAD_LO:1010 Kind = ELF::R_RISCV_TLSDESC_LOAD_LO12;1011 break;1012 case RISCVII::MO_TLSDESC_ADD_LO:1013 Kind = ELF::R_RISCV_TLSDESC_ADD_LO12;1014 break;1015 case RISCVII::MO_TLSDESC_CALL:1016 Kind = ELF::R_RISCV_TLSDESC_CALL;1017 break;1018 }1019 1020 const MCExpr *ME = MCSymbolRefExpr::create(Sym, Ctx);1021 1022 if (!MO.isJTI() && !MO.isMBB() && MO.getOffset())1023 ME = MCBinaryExpr::createAdd(1024 ME, MCConstantExpr::create(MO.getOffset(), Ctx), Ctx);1025 1026 if (Kind != RISCV::S_None)1027 ME = MCSpecifierExpr::create(ME, Kind, Ctx);1028 return MCOperand::createExpr(ME);1029}1030 1031bool RISCVAsmPrinter::lowerOperand(const MachineOperand &MO,1032 MCOperand &MCOp) const {1033 switch (MO.getType()) {1034 default:1035 report_fatal_error("lowerOperand: unknown operand type");1036 case MachineOperand::MO_Register:1037 // Ignore all implicit register operands.1038 if (MO.isImplicit())1039 return false;1040 MCOp = MCOperand::createReg(MO.getReg());1041 break;1042 case MachineOperand::MO_RegisterMask:1043 // Regmasks are like implicit defs.1044 return false;1045 case MachineOperand::MO_Immediate:1046 MCOp = MCOperand::createImm(MO.getImm());1047 break;1048 case MachineOperand::MO_MachineBasicBlock:1049 MCOp = lowerSymbolOperand(MO, MO.getMBB()->getSymbol(), *this);1050 break;1051 case MachineOperand::MO_GlobalAddress:1052 MCOp = lowerSymbolOperand(MO, getSymbolPreferLocal(*MO.getGlobal()), *this);1053 break;1054 case MachineOperand::MO_BlockAddress:1055 MCOp = lowerSymbolOperand(MO, GetBlockAddressSymbol(MO.getBlockAddress()),1056 *this);1057 break;1058 case MachineOperand::MO_ExternalSymbol:1059 MCOp = lowerSymbolOperand(MO, GetExternalSymbolSymbol(MO.getSymbolName()),1060 *this);1061 break;1062 case MachineOperand::MO_ConstantPoolIndex:1063 MCOp = lowerSymbolOperand(MO, GetCPISymbol(MO.getIndex()), *this);1064 break;1065 case MachineOperand::MO_JumpTableIndex:1066 MCOp = lowerSymbolOperand(MO, GetJTISymbol(MO.getIndex()), *this);1067 break;1068 case MachineOperand::MO_MCSymbol:1069 MCOp = lowerSymbolOperand(MO, MO.getMCSymbol(), *this);1070 break;1071 }1072 return true;1073}1074 1075static bool lowerRISCVVMachineInstrToMCInst(const MachineInstr *MI,1076 MCInst &OutMI,1077 const RISCVSubtarget *STI) {1078 const RISCVVPseudosTable::PseudoInfo *RVV =1079 RISCVVPseudosTable::getPseudoInfo(MI->getOpcode());1080 if (!RVV)1081 return false;1082 1083 OutMI.setOpcode(RVV->BaseInstr);1084 1085 const TargetInstrInfo *TII = STI->getInstrInfo();1086 const TargetRegisterInfo *TRI = STI->getRegisterInfo();1087 assert(TRI && "TargetRegisterInfo expected");1088 1089 const MCInstrDesc &MCID = MI->getDesc();1090 uint64_t TSFlags = MCID.TSFlags;1091 unsigned NumOps = MI->getNumExplicitOperands();1092 1093 // Skip policy, SEW, VL, VXRM/FRM operands which are the last operands if1094 // present.1095 if (RISCVII::hasVecPolicyOp(TSFlags))1096 --NumOps;1097 if (RISCVII::hasSEWOp(TSFlags))1098 --NumOps;1099 if (RISCVII::hasVLOp(TSFlags))1100 --NumOps;1101 if (RISCVII::hasRoundModeOp(TSFlags))1102 --NumOps;1103 if (RISCVII::hasTWidenOp(TSFlags))1104 --NumOps;1105 if (RISCVII::hasTMOp(TSFlags))1106 --NumOps;1107 if (RISCVII::hasTKOp(TSFlags))1108 --NumOps;1109 1110 bool hasVLOutput = RISCVInstrInfo::isFaultOnlyFirstLoad(*MI);1111 for (unsigned OpNo = 0; OpNo != NumOps; ++OpNo) {1112 const MachineOperand &MO = MI->getOperand(OpNo);1113 // Skip vl output. It should be the second output.1114 if (hasVLOutput && OpNo == 1)1115 continue;1116 1117 // Skip passthru op. It should be the first operand after the defs.1118 if (OpNo == MI->getNumExplicitDefs() && MO.isReg() && MO.isTied()) {1119 assert(MCID.getOperandConstraint(OpNo, MCOI::TIED_TO) == 0 &&1120 "Expected tied to first def.");1121 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());1122 // Skip if the next operand in OutMI is not supposed to be tied. Unless it1123 // is a _TIED instruction.1124 if (OutMCID.getOperandConstraint(OutMI.getNumOperands(), MCOI::TIED_TO) <1125 0 &&1126 !RISCVII::isTiedPseudo(TSFlags))1127 continue;1128 }1129 1130 MCOperand MCOp;1131 switch (MO.getType()) {1132 default:1133 llvm_unreachable("Unknown operand type");1134 case MachineOperand::MO_Register: {1135 Register Reg = MO.getReg();1136 1137 if (RISCV::VRM2RegClass.contains(Reg) ||1138 RISCV::VRM4RegClass.contains(Reg) ||1139 RISCV::VRM8RegClass.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)) {1143 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) ||1150 RISCV::VRN2M2RegClass.contains(Reg) ||1151 RISCV::VRN2M4RegClass.contains(Reg) ||1152 RISCV::VRN3M1RegClass.contains(Reg) ||1153 RISCV::VRN3M2RegClass.contains(Reg) ||1154 RISCV::VRN4M1RegClass.contains(Reg) ||1155 RISCV::VRN4M2RegClass.contains(Reg) ||1156 RISCV::VRN5M1RegClass.contains(Reg) ||1157 RISCV::VRN6M1RegClass.contains(Reg) ||1158 RISCV::VRN7M1RegClass.contains(Reg) ||1159 RISCV::VRN8M1RegClass.contains(Reg)) {1160 Reg = TRI->getSubReg(Reg, RISCV::sub_vrm1_0);1161 assert(Reg && "Subregister does not exist");1162 }1163 1164 MCOp = MCOperand::createReg(Reg);1165 break;1166 }1167 case MachineOperand::MO_Immediate:1168 MCOp = MCOperand::createImm(MO.getImm());1169 break;1170 }1171 OutMI.addOperand(MCOp);1172 }1173 1174 // Unmasked pseudo instructions need to append dummy mask operand to1175 // V instructions. All V instructions are modeled as the masked version.1176 const MCInstrDesc &OutMCID = TII->get(OutMI.getOpcode());1177 if (OutMI.getNumOperands() < OutMCID.getNumOperands()) {1178 assert(OutMCID.operands()[OutMI.getNumOperands()].RegClass ==1179 RISCV::VMV0RegClassID &&1180 "Expected only mask operand to be missing");1181 OutMI.addOperand(MCOperand::createReg(RISCV::NoRegister));1182 }1183 1184 assert(OutMI.getNumOperands() == OutMCID.getNumOperands());1185 return true;1186}1187 1188void RISCVAsmPrinter::lowerToMCInst(const MachineInstr *MI, MCInst &OutMI) {1189 if (lowerRISCVVMachineInstrToMCInst(MI, OutMI, STI))1190 return;1191 1192 OutMI.setOpcode(MI->getOpcode());1193 1194 for (const MachineOperand &MO : MI->operands()) {1195 MCOperand MCOp;1196 if (lowerOperand(MO, MCOp))1197 OutMI.addOperand(MCOp);1198 }1199}1200 1201void RISCVAsmPrinter::emitMachineConstantPoolValue(1202 MachineConstantPoolValue *MCPV) {1203 auto *RCPV = static_cast<RISCVConstantPoolValue *>(MCPV);1204 MCSymbol *MCSym;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 1215 const MCExpr *Expr = MCSymbolRefExpr::create(MCSym, OutContext);1216 uint64_t Size = getDataLayout().getTypeAllocSize(RCPV->getType());1217 OutStreamer->emitValue(Expr, Size);1218}1219 1220char RISCVAsmPrinter::ID = 0;1221 1222INITIALIZE_PASS(RISCVAsmPrinter, "riscv-asm-printer", "RISC-V Assembly Printer",1223 false, false)1224