brintos

brintos / llvm-project-archived public Read only

0
0
Text · 42.7 KiB · de433e4 Raw
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