1 //===-- RISCVAsmPrinter.cpp - RISCV LLVM assembly writer ------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains a printer that converts from our internal representation 10 // of machine-dependent LLVM code to the RISCV assembly language. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "MCTargetDesc/RISCVInstPrinter.h" 15 #include "MCTargetDesc/RISCVMCExpr.h" 16 #include "MCTargetDesc/RISCVTargetStreamer.h" 17 #include "RISCV.h" 18 #include "RISCVMachineFunctionInfo.h" 19 #include "RISCVTargetMachine.h" 20 #include "TargetInfo/RISCVTargetInfo.h" 21 #include "llvm/ADT/Statistic.h" 22 #include "llvm/BinaryFormat/ELF.h" 23 #include "llvm/CodeGen/AsmPrinter.h" 24 #include "llvm/CodeGen/MachineConstantPool.h" 25 #include "llvm/CodeGen/MachineFunctionPass.h" 26 #include "llvm/CodeGen/MachineInstr.h" 27 #include "llvm/CodeGen/MachineModuleInfo.h" 28 #include "llvm/MC/MCAsmInfo.h" 29 #include "llvm/MC/MCContext.h" 30 #include "llvm/MC/MCInst.h" 31 #include "llvm/MC/MCInstBuilder.h" 32 #include "llvm/MC/MCObjectFileInfo.h" 33 #include "llvm/MC/MCSectionELF.h" 34 #include "llvm/MC/MCStreamer.h" 35 #include "llvm/MC/MCSymbol.h" 36 #include "llvm/MC/TargetRegistry.h" 37 #include "llvm/Support/raw_ostream.h" 38 #include "llvm/Transforms/Instrumentation/HWAddressSanitizer.h" 39 40 using namespace llvm; 41 42 #define DEBUG_TYPE "asm-printer" 43 44 STATISTIC(RISCVNumInstrsCompressed, 45 "Number of RISC-V Compressed instructions emitted"); 46 47 namespace { 48 class RISCVAsmPrinter : public AsmPrinter { 49 const RISCVSubtarget *STI; 50 51 public: 52 explicit RISCVAsmPrinter(TargetMachine &TM, 53 std::unique_ptr<MCStreamer> Streamer) 54 : AsmPrinter(TM, std::move(Streamer)) {} 55 56 StringRef getPassName() const override { return "RISCV Assembly Printer"; } 57 58 bool runOnMachineFunction(MachineFunction &MF) override; 59 60 void emitInstruction(const MachineInstr *MI) override; 61 62 bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 63 const char *ExtraCode, raw_ostream &OS) override; 64 bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, 65 const char *ExtraCode, raw_ostream &OS) override; 66 67 void EmitToStreamer(MCStreamer &S, const MCInst &Inst); 68 bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, 69 const MachineInstr *MI); 70 71 typedef std::tuple<unsigned, uint32_t> HwasanMemaccessTuple; 72 std::map<HwasanMemaccessTuple, MCSymbol *> HwasanMemaccessSymbols; 73 void LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI); 74 void EmitHwasanMemaccessSymbols(Module &M); 75 76 // Wrapper needed for tblgenned pseudo lowering. 77 bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp) const { 78 return lowerRISCVMachineOperandToMCOperand(MO, MCOp, *this); 79 } 80 81 void emitStartOfAsmFile(Module &M) override; 82 void emitEndOfAsmFile(Module &M) override; 83 84 void emitFunctionEntryLabel() override; 85 86 private: 87 void emitAttributes(); 88 }; 89 } 90 91 void RISCVAsmPrinter::EmitToStreamer(MCStreamer &S, const MCInst &Inst) { 92 MCInst CInst; 93 bool Res = RISCVRVC::compress(CInst, Inst, *STI); 94 if (Res) 95 ++RISCVNumInstrsCompressed; 96 AsmPrinter::EmitToStreamer(*OutStreamer, Res ? CInst : Inst); 97 } 98 99 // Simple pseudo-instructions have their lowering (with expansion to real 100 // instructions) auto-generated. 101 #include "RISCVGenMCPseudoLowering.inc" 102 103 void RISCVAsmPrinter::emitInstruction(const MachineInstr *MI) { 104 RISCV_MC::verifyInstructionPredicates(MI->getOpcode(), 105 getSubtargetInfo().getFeatureBits()); 106 107 // Do any auto-generated pseudo lowerings. 108 if (emitPseudoExpansionLowering(*OutStreamer, MI)) 109 return; 110 111 112 switch (MI->getOpcode()) { 113 case RISCV::HWASAN_CHECK_MEMACCESS_SHORTGRANULES: 114 LowerHWASAN_CHECK_MEMACCESS(*MI); 115 return; 116 } 117 118 MCInst TmpInst; 119 if (!lowerRISCVMachineInstrToMCInst(MI, TmpInst, *this)) 120 EmitToStreamer(*OutStreamer, TmpInst); 121 } 122 123 bool RISCVAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 124 const char *ExtraCode, raw_ostream &OS) { 125 // First try the generic code, which knows about modifiers like 'c' and 'n'. 126 if (!AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS)) 127 return false; 128 129 const MachineOperand &MO = MI->getOperand(OpNo); 130 if (ExtraCode && ExtraCode[0]) { 131 if (ExtraCode[1] != 0) 132 return true; // Unknown modifier. 133 134 switch (ExtraCode[0]) { 135 default: 136 return true; // Unknown modifier. 137 case 'z': // Print zero register if zero, regular printing otherwise. 138 if (MO.isImm() && MO.getImm() == 0) { 139 OS << RISCVInstPrinter::getRegisterName(RISCV::X0); 140 return false; 141 } 142 break; 143 case 'i': // Literal 'i' if operand is not a register. 144 if (!MO.isReg()) 145 OS << 'i'; 146 return false; 147 } 148 } 149 150 switch (MO.getType()) { 151 case MachineOperand::MO_Immediate: 152 OS << MO.getImm(); 153 return false; 154 case MachineOperand::MO_Register: 155 OS << RISCVInstPrinter::getRegisterName(MO.getReg()); 156 return false; 157 case MachineOperand::MO_GlobalAddress: 158 PrintSymbolOperand(MO, OS); 159 return false; 160 case MachineOperand::MO_BlockAddress: { 161 MCSymbol *Sym = GetBlockAddressSymbol(MO.getBlockAddress()); 162 Sym->print(OS, MAI); 163 return false; 164 } 165 default: 166 break; 167 } 168 169 return true; 170 } 171 172 bool RISCVAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 173 unsigned OpNo, 174 const char *ExtraCode, 175 raw_ostream &OS) { 176 if (!ExtraCode) { 177 const MachineOperand &MO = MI->getOperand(OpNo); 178 // For now, we only support register memory operands in registers and 179 // assume there is no addend 180 if (!MO.isReg()) 181 return true; 182 183 OS << "0(" << RISCVInstPrinter::getRegisterName(MO.getReg()) << ")"; 184 return false; 185 } 186 187 return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS); 188 } 189 190 bool RISCVAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 191 STI = &MF.getSubtarget<RISCVSubtarget>(); 192 193 SetupMachineFunction(MF); 194 emitFunctionBody(); 195 return false; 196 } 197 198 void RISCVAsmPrinter::emitStartOfAsmFile(Module &M) { 199 RISCVTargetStreamer &RTS = 200 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); 201 if (const MDString *ModuleTargetABI = 202 dyn_cast_or_null<MDString>(M.getModuleFlag("target-abi"))) 203 RTS.setTargetABI(RISCVABI::getTargetABI(ModuleTargetABI->getString())); 204 if (TM.getTargetTriple().isOSBinFormatELF()) 205 emitAttributes(); 206 } 207 208 void RISCVAsmPrinter::emitEndOfAsmFile(Module &M) { 209 RISCVTargetStreamer &RTS = 210 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); 211 212 if (TM.getTargetTriple().isOSBinFormatELF()) 213 RTS.finishAttributeSection(); 214 EmitHwasanMemaccessSymbols(M); 215 } 216 217 void RISCVAsmPrinter::emitAttributes() { 218 RISCVTargetStreamer &RTS = 219 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); 220 // Use MCSubtargetInfo from TargetMachine. Individual functions may have 221 // attributes that differ from other functions in the module and we have no 222 // way to know which function is correct. 223 RTS.emitTargetAttributes(*TM.getMCSubtargetInfo()); 224 } 225 226 void RISCVAsmPrinter::emitFunctionEntryLabel() { 227 const auto *RMFI = MF->getInfo<RISCVMachineFunctionInfo>(); 228 if (RMFI->isVectorCall()) { 229 auto &RTS = 230 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); 231 RTS.emitDirectiveVariantCC(*CurrentFnSym); 232 } 233 return AsmPrinter::emitFunctionEntryLabel(); 234 } 235 236 // Force static initialization. 237 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVAsmPrinter() { 238 RegisterAsmPrinter<RISCVAsmPrinter> X(getTheRISCV32Target()); 239 RegisterAsmPrinter<RISCVAsmPrinter> Y(getTheRISCV64Target()); 240 } 241 242 void RISCVAsmPrinter::LowerHWASAN_CHECK_MEMACCESS(const MachineInstr &MI) { 243 Register Reg = MI.getOperand(0).getReg(); 244 uint32_t AccessInfo = MI.getOperand(1).getImm(); 245 MCSymbol *&Sym = 246 HwasanMemaccessSymbols[HwasanMemaccessTuple(Reg, AccessInfo)]; 247 if (!Sym) { 248 // FIXME: Make this work on non-ELF. 249 if (!TM.getTargetTriple().isOSBinFormatELF()) 250 report_fatal_error("llvm.hwasan.check.memaccess only supported on ELF"); 251 252 std::string SymName = "__hwasan_check_x" + utostr(Reg - RISCV::X0) + "_" + 253 utostr(AccessInfo) + "_short"; 254 Sym = OutContext.getOrCreateSymbol(SymName); 255 } 256 auto Res = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, OutContext); 257 auto Expr = RISCVMCExpr::create(Res, RISCVMCExpr::VK_RISCV_CALL, OutContext); 258 259 EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr)); 260 } 261 262 void RISCVAsmPrinter::EmitHwasanMemaccessSymbols(Module &M) { 263 if (HwasanMemaccessSymbols.empty()) 264 return; 265 266 assert(TM.getTargetTriple().isOSBinFormatELF()); 267 // Use MCSubtargetInfo from TargetMachine. Individual functions may have 268 // attributes that differ from other functions in the module and we have no 269 // way to know which function is correct. 270 const MCSubtargetInfo &MCSTI = *TM.getMCSubtargetInfo(); 271 272 MCSymbol *HwasanTagMismatchV2Sym = 273 OutContext.getOrCreateSymbol("__hwasan_tag_mismatch_v2"); 274 // Annotate symbol as one having incompatible calling convention, so 275 // run-time linkers can instead eagerly bind this function. 276 auto &RTS = 277 static_cast<RISCVTargetStreamer &>(*OutStreamer->getTargetStreamer()); 278 RTS.emitDirectiveVariantCC(*HwasanTagMismatchV2Sym); 279 280 const MCSymbolRefExpr *HwasanTagMismatchV2Ref = 281 MCSymbolRefExpr::create(HwasanTagMismatchV2Sym, OutContext); 282 auto Expr = RISCVMCExpr::create(HwasanTagMismatchV2Ref, 283 RISCVMCExpr::VK_RISCV_CALL, OutContext); 284 285 for (auto &P : HwasanMemaccessSymbols) { 286 unsigned Reg = std::get<0>(P.first); 287 uint32_t AccessInfo = std::get<1>(P.first); 288 MCSymbol *Sym = P.second; 289 290 unsigned Size = 291 1 << ((AccessInfo >> HWASanAccessInfo::AccessSizeShift) & 0xf); 292 OutStreamer->switchSection(OutContext.getELFSection( 293 ".text.hot", ELF::SHT_PROGBITS, 294 ELF::SHF_EXECINSTR | ELF::SHF_ALLOC | ELF::SHF_GROUP, 0, Sym->getName(), 295 /*IsComdat=*/true)); 296 297 OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction); 298 OutStreamer->emitSymbolAttribute(Sym, MCSA_Weak); 299 OutStreamer->emitSymbolAttribute(Sym, MCSA_Hidden); 300 OutStreamer->emitLabel(Sym); 301 302 // Extract shadow offset from ptr 303 OutStreamer->emitInstruction( 304 MCInstBuilder(RISCV::SLLI).addReg(RISCV::X6).addReg(Reg).addImm(8), 305 MCSTI); 306 OutStreamer->emitInstruction(MCInstBuilder(RISCV::SRLI) 307 .addReg(RISCV::X6) 308 .addReg(RISCV::X6) 309 .addImm(12), 310 MCSTI); 311 // load shadow tag in X6, X5 contains shadow base 312 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADD) 313 .addReg(RISCV::X6) 314 .addReg(RISCV::X5) 315 .addReg(RISCV::X6), 316 MCSTI); 317 OutStreamer->emitInstruction( 318 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0), 319 MCSTI); 320 // Extract tag from X5 and compare it with loaded tag from shadow 321 OutStreamer->emitInstruction( 322 MCInstBuilder(RISCV::SRLI).addReg(RISCV::X7).addReg(Reg).addImm(56), 323 MCSTI); 324 MCSymbol *HandleMismatchOrPartialSym = OutContext.createTempSymbol(); 325 // X7 contains tag from memory, while X6 contains tag from the pointer 326 OutStreamer->emitInstruction( 327 MCInstBuilder(RISCV::BNE) 328 .addReg(RISCV::X7) 329 .addReg(RISCV::X6) 330 .addExpr(MCSymbolRefExpr::create(HandleMismatchOrPartialSym, 331 OutContext)), 332 MCSTI); 333 MCSymbol *ReturnSym = OutContext.createTempSymbol(); 334 OutStreamer->emitLabel(ReturnSym); 335 OutStreamer->emitInstruction(MCInstBuilder(RISCV::JALR) 336 .addReg(RISCV::X0) 337 .addReg(RISCV::X1) 338 .addImm(0), 339 MCSTI); 340 OutStreamer->emitLabel(HandleMismatchOrPartialSym); 341 342 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI) 343 .addReg(RISCV::X28) 344 .addReg(RISCV::X0) 345 .addImm(16), 346 MCSTI); 347 MCSymbol *HandleMismatchSym = OutContext.createTempSymbol(); 348 OutStreamer->emitInstruction( 349 MCInstBuilder(RISCV::BGEU) 350 .addReg(RISCV::X6) 351 .addReg(RISCV::X28) 352 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)), 353 MCSTI); 354 355 OutStreamer->emitInstruction( 356 MCInstBuilder(RISCV::ANDI).addReg(RISCV::X28).addReg(Reg).addImm(0xF), 357 MCSTI); 358 359 if (Size != 1) 360 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI) 361 .addReg(RISCV::X28) 362 .addReg(RISCV::X28) 363 .addImm(Size - 1), 364 MCSTI); 365 OutStreamer->emitInstruction( 366 MCInstBuilder(RISCV::BGE) 367 .addReg(RISCV::X28) 368 .addReg(RISCV::X6) 369 .addExpr(MCSymbolRefExpr::create(HandleMismatchSym, OutContext)), 370 MCSTI); 371 372 OutStreamer->emitInstruction( 373 MCInstBuilder(RISCV::ORI).addReg(RISCV::X6).addReg(Reg).addImm(0xF), 374 MCSTI); 375 OutStreamer->emitInstruction( 376 MCInstBuilder(RISCV::LBU).addReg(RISCV::X6).addReg(RISCV::X6).addImm(0), 377 MCSTI); 378 OutStreamer->emitInstruction( 379 MCInstBuilder(RISCV::BEQ) 380 .addReg(RISCV::X6) 381 .addReg(RISCV::X7) 382 .addExpr(MCSymbolRefExpr::create(ReturnSym, OutContext)), 383 MCSTI); 384 385 OutStreamer->emitLabel(HandleMismatchSym); 386 387 // | Previous stack frames... | 388 // +=================================+ <-- [SP + 256] 389 // | ... | 390 // | | 391 // | Stack frame space for x12 - x31.| 392 // | | 393 // | ... | 394 // +---------------------------------+ <-- [SP + 96] 395 // | Saved x11(arg1), as | 396 // | __hwasan_check_* clobbers it. | 397 // +---------------------------------+ <-- [SP + 88] 398 // | Saved x10(arg0), as | 399 // | __hwasan_check_* clobbers it. | 400 // +---------------------------------+ <-- [SP + 80] 401 // | | 402 // | Stack frame space for x9. | 403 // +---------------------------------+ <-- [SP + 72] 404 // | | 405 // | Saved x8(fp), as | 406 // | __hwasan_check_* clobbers it. | 407 // +---------------------------------+ <-- [SP + 64] 408 // | ... | 409 // | | 410 // | Stack frame space for x2 - x7. | 411 // | | 412 // | ... | 413 // +---------------------------------+ <-- [SP + 16] 414 // | Return address (x1) for caller | 415 // | of __hwasan_check_*. | 416 // +---------------------------------+ <-- [SP + 8] 417 // | Reserved place for x0, possibly | 418 // | junk, since we don't save it. | 419 // +---------------------------------+ <-- [x2 / SP] 420 421 // Adjust sp 422 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI) 423 .addReg(RISCV::X2) 424 .addReg(RISCV::X2) 425 .addImm(-256), 426 MCSTI); 427 428 // store x10(arg0) by new sp 429 OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD) 430 .addReg(RISCV::X10) 431 .addReg(RISCV::X2) 432 .addImm(8 * 10), 433 MCSTI); 434 // store x11(arg1) by new sp 435 OutStreamer->emitInstruction(MCInstBuilder(RISCV::SD) 436 .addReg(RISCV::X11) 437 .addReg(RISCV::X2) 438 .addImm(8 * 11), 439 MCSTI); 440 441 // store x8(fp) by new sp 442 OutStreamer->emitInstruction( 443 MCInstBuilder(RISCV::SD).addReg(RISCV::X8).addReg(RISCV::X2).addImm(8 * 444 8), 445 MCSTI); 446 // store x1(ra) by new sp 447 OutStreamer->emitInstruction( 448 MCInstBuilder(RISCV::SD).addReg(RISCV::X1).addReg(RISCV::X2).addImm(1 * 449 8), 450 MCSTI); 451 if (Reg != RISCV::X10) 452 OutStreamer->emitInstruction(MCInstBuilder(RISCV::ADDI) 453 .addReg(RISCV::X10) 454 .addReg(Reg) 455 .addImm(0), 456 MCSTI); 457 OutStreamer->emitInstruction( 458 MCInstBuilder(RISCV::ADDI) 459 .addReg(RISCV::X11) 460 .addReg(RISCV::X0) 461 .addImm(AccessInfo & HWASanAccessInfo::RuntimeMask), 462 MCSTI); 463 464 OutStreamer->emitInstruction(MCInstBuilder(RISCV::PseudoCALL).addExpr(Expr), 465 MCSTI); 466 } 467 } 468