1 //===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===// 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 // Streams SystemZ assembly language and associated data, in the form of 10 // MCInsts and MCExprs respectively. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "SystemZAsmPrinter.h" 15 #include "MCTargetDesc/SystemZInstPrinter.h" 16 #include "SystemZConstantPoolValue.h" 17 #include "SystemZMCInstLower.h" 18 #include "TargetInfo/SystemZTargetInfo.h" 19 #include "llvm/BinaryFormat/ELF.h" 20 #include "llvm/CodeGen/MachineModuleInfoImpls.h" 21 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 22 #include "llvm/IR/Mangler.h" 23 #include "llvm/MC/MCExpr.h" 24 #include "llvm/MC/MCInstBuilder.h" 25 #include "llvm/MC/MCSectionELF.h" 26 #include "llvm/MC/MCStreamer.h" 27 #include "llvm/Support/TargetRegistry.h" 28 29 using namespace llvm; 30 31 // Return an RI instruction like MI with opcode Opcode, but with the 32 // GR64 register operands turned into GR32s. 33 static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) { 34 if (MI->isCompare()) 35 return MCInstBuilder(Opcode) 36 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 37 .addImm(MI->getOperand(1).getImm()); 38 else 39 return MCInstBuilder(Opcode) 40 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 41 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg())) 42 .addImm(MI->getOperand(2).getImm()); 43 } 44 45 // Return an RI instruction like MI with opcode Opcode, but with the 46 // GR64 register operands turned into GRH32s. 47 static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) { 48 if (MI->isCompare()) 49 return MCInstBuilder(Opcode) 50 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 51 .addImm(MI->getOperand(1).getImm()); 52 else 53 return MCInstBuilder(Opcode) 54 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 55 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg())) 56 .addImm(MI->getOperand(2).getImm()); 57 } 58 59 // Return an RI instruction like MI with opcode Opcode, but with the 60 // R2 register turned into a GR64. 61 static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) { 62 return MCInstBuilder(Opcode) 63 .addReg(MI->getOperand(0).getReg()) 64 .addReg(MI->getOperand(1).getReg()) 65 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())) 66 .addImm(MI->getOperand(3).getImm()) 67 .addImm(MI->getOperand(4).getImm()) 68 .addImm(MI->getOperand(5).getImm()); 69 } 70 71 static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) { 72 StringRef Name = "__tls_get_offset"; 73 return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name), 74 MCSymbolRefExpr::VK_PLT, 75 Context); 76 } 77 78 static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) { 79 StringRef Name = "_GLOBAL_OFFSET_TABLE_"; 80 return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name), 81 MCSymbolRefExpr::VK_None, 82 Context); 83 } 84 85 // MI is an instruction that accepts an optional alignment hint, 86 // and which was already lowered to LoweredMI. If the alignment 87 // of the original memory operand is known, update LoweredMI to 88 // an instruction with the corresponding hint set. 89 static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI, 90 unsigned Opcode) { 91 if (!MI->hasOneMemOperand()) 92 return; 93 const MachineMemOperand *MMO = *MI->memoperands_begin(); 94 unsigned AlignmentHint = 0; 95 if (MMO->getAlign() >= Align(16)) 96 AlignmentHint = 4; 97 else if (MMO->getAlign() >= Align(8)) 98 AlignmentHint = 3; 99 if (AlignmentHint == 0) 100 return; 101 102 LoweredMI.setOpcode(Opcode); 103 LoweredMI.addOperand(MCOperand::createImm(AlignmentHint)); 104 } 105 106 // MI loads the high part of a vector from memory. Return an instruction 107 // that uses replicating vector load Opcode to do the same thing. 108 static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) { 109 return MCInstBuilder(Opcode) 110 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 111 .addReg(MI->getOperand(1).getReg()) 112 .addImm(MI->getOperand(2).getImm()) 113 .addReg(MI->getOperand(3).getReg()); 114 } 115 116 // MI stores the high part of a vector to memory. Return an instruction 117 // that uses elemental vector store Opcode to do the same thing. 118 static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) { 119 return MCInstBuilder(Opcode) 120 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 121 .addReg(MI->getOperand(1).getReg()) 122 .addImm(MI->getOperand(2).getImm()) 123 .addReg(MI->getOperand(3).getReg()) 124 .addImm(0); 125 } 126 127 void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { 128 SystemZMCInstLower Lower(MF->getContext(), *this); 129 MCInst LoweredMI; 130 switch (MI->getOpcode()) { 131 case SystemZ::Return: 132 LoweredMI = MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D); 133 break; 134 135 case SystemZ::CondReturn: 136 LoweredMI = MCInstBuilder(SystemZ::BCR) 137 .addImm(MI->getOperand(0).getImm()) 138 .addImm(MI->getOperand(1).getImm()) 139 .addReg(SystemZ::R14D); 140 break; 141 142 case SystemZ::CRBReturn: 143 LoweredMI = MCInstBuilder(SystemZ::CRB) 144 .addReg(MI->getOperand(0).getReg()) 145 .addReg(MI->getOperand(1).getReg()) 146 .addImm(MI->getOperand(2).getImm()) 147 .addReg(SystemZ::R14D) 148 .addImm(0); 149 break; 150 151 case SystemZ::CGRBReturn: 152 LoweredMI = MCInstBuilder(SystemZ::CGRB) 153 .addReg(MI->getOperand(0).getReg()) 154 .addReg(MI->getOperand(1).getReg()) 155 .addImm(MI->getOperand(2).getImm()) 156 .addReg(SystemZ::R14D) 157 .addImm(0); 158 break; 159 160 case SystemZ::CIBReturn: 161 LoweredMI = MCInstBuilder(SystemZ::CIB) 162 .addReg(MI->getOperand(0).getReg()) 163 .addImm(MI->getOperand(1).getImm()) 164 .addImm(MI->getOperand(2).getImm()) 165 .addReg(SystemZ::R14D) 166 .addImm(0); 167 break; 168 169 case SystemZ::CGIBReturn: 170 LoweredMI = MCInstBuilder(SystemZ::CGIB) 171 .addReg(MI->getOperand(0).getReg()) 172 .addImm(MI->getOperand(1).getImm()) 173 .addImm(MI->getOperand(2).getImm()) 174 .addReg(SystemZ::R14D) 175 .addImm(0); 176 break; 177 178 case SystemZ::CLRBReturn: 179 LoweredMI = MCInstBuilder(SystemZ::CLRB) 180 .addReg(MI->getOperand(0).getReg()) 181 .addReg(MI->getOperand(1).getReg()) 182 .addImm(MI->getOperand(2).getImm()) 183 .addReg(SystemZ::R14D) 184 .addImm(0); 185 break; 186 187 case SystemZ::CLGRBReturn: 188 LoweredMI = MCInstBuilder(SystemZ::CLGRB) 189 .addReg(MI->getOperand(0).getReg()) 190 .addReg(MI->getOperand(1).getReg()) 191 .addImm(MI->getOperand(2).getImm()) 192 .addReg(SystemZ::R14D) 193 .addImm(0); 194 break; 195 196 case SystemZ::CLIBReturn: 197 LoweredMI = MCInstBuilder(SystemZ::CLIB) 198 .addReg(MI->getOperand(0).getReg()) 199 .addImm(MI->getOperand(1).getImm()) 200 .addImm(MI->getOperand(2).getImm()) 201 .addReg(SystemZ::R14D) 202 .addImm(0); 203 break; 204 205 case SystemZ::CLGIBReturn: 206 LoweredMI = MCInstBuilder(SystemZ::CLGIB) 207 .addReg(MI->getOperand(0).getReg()) 208 .addImm(MI->getOperand(1).getImm()) 209 .addImm(MI->getOperand(2).getImm()) 210 .addReg(SystemZ::R14D) 211 .addImm(0); 212 break; 213 214 case SystemZ::CallBRASL: 215 LoweredMI = MCInstBuilder(SystemZ::BRASL) 216 .addReg(SystemZ::R14D) 217 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 218 break; 219 220 case SystemZ::CallBASR: 221 LoweredMI = MCInstBuilder(SystemZ::BASR) 222 .addReg(SystemZ::R14D) 223 .addReg(MI->getOperand(0).getReg()); 224 break; 225 226 case SystemZ::CallJG: 227 LoweredMI = MCInstBuilder(SystemZ::JG) 228 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 229 break; 230 231 case SystemZ::CallBRCL: 232 LoweredMI = MCInstBuilder(SystemZ::BRCL) 233 .addImm(MI->getOperand(0).getImm()) 234 .addImm(MI->getOperand(1).getImm()) 235 .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT)); 236 break; 237 238 case SystemZ::CallBR: 239 LoweredMI = MCInstBuilder(SystemZ::BR) 240 .addReg(MI->getOperand(0).getReg()); 241 break; 242 243 case SystemZ::CallBCR: 244 LoweredMI = MCInstBuilder(SystemZ::BCR) 245 .addImm(MI->getOperand(0).getImm()) 246 .addImm(MI->getOperand(1).getImm()) 247 .addReg(MI->getOperand(2).getReg()); 248 break; 249 250 case SystemZ::CRBCall: 251 LoweredMI = MCInstBuilder(SystemZ::CRB) 252 .addReg(MI->getOperand(0).getReg()) 253 .addReg(MI->getOperand(1).getReg()) 254 .addImm(MI->getOperand(2).getImm()) 255 .addReg(MI->getOperand(3).getReg()) 256 .addImm(0); 257 break; 258 259 case SystemZ::CGRBCall: 260 LoweredMI = MCInstBuilder(SystemZ::CGRB) 261 .addReg(MI->getOperand(0).getReg()) 262 .addReg(MI->getOperand(1).getReg()) 263 .addImm(MI->getOperand(2).getImm()) 264 .addReg(MI->getOperand(3).getReg()) 265 .addImm(0); 266 break; 267 268 case SystemZ::CIBCall: 269 LoweredMI = MCInstBuilder(SystemZ::CIB) 270 .addReg(MI->getOperand(0).getReg()) 271 .addImm(MI->getOperand(1).getImm()) 272 .addImm(MI->getOperand(2).getImm()) 273 .addReg(MI->getOperand(3).getReg()) 274 .addImm(0); 275 break; 276 277 case SystemZ::CGIBCall: 278 LoweredMI = MCInstBuilder(SystemZ::CGIB) 279 .addReg(MI->getOperand(0).getReg()) 280 .addImm(MI->getOperand(1).getImm()) 281 .addImm(MI->getOperand(2).getImm()) 282 .addReg(MI->getOperand(3).getReg()) 283 .addImm(0); 284 break; 285 286 case SystemZ::CLRBCall: 287 LoweredMI = MCInstBuilder(SystemZ::CLRB) 288 .addReg(MI->getOperand(0).getReg()) 289 .addReg(MI->getOperand(1).getReg()) 290 .addImm(MI->getOperand(2).getImm()) 291 .addReg(MI->getOperand(3).getReg()) 292 .addImm(0); 293 break; 294 295 case SystemZ::CLGRBCall: 296 LoweredMI = MCInstBuilder(SystemZ::CLGRB) 297 .addReg(MI->getOperand(0).getReg()) 298 .addReg(MI->getOperand(1).getReg()) 299 .addImm(MI->getOperand(2).getImm()) 300 .addReg(MI->getOperand(3).getReg()) 301 .addImm(0); 302 break; 303 304 case SystemZ::CLIBCall: 305 LoweredMI = MCInstBuilder(SystemZ::CLIB) 306 .addReg(MI->getOperand(0).getReg()) 307 .addImm(MI->getOperand(1).getImm()) 308 .addImm(MI->getOperand(2).getImm()) 309 .addReg(MI->getOperand(3).getReg()) 310 .addImm(0); 311 break; 312 313 case SystemZ::CLGIBCall: 314 LoweredMI = MCInstBuilder(SystemZ::CLGIB) 315 .addReg(MI->getOperand(0).getReg()) 316 .addImm(MI->getOperand(1).getImm()) 317 .addImm(MI->getOperand(2).getImm()) 318 .addReg(MI->getOperand(3).getReg()) 319 .addImm(0); 320 break; 321 322 case SystemZ::TLS_GDCALL: 323 LoweredMI = MCInstBuilder(SystemZ::BRASL) 324 .addReg(SystemZ::R14D) 325 .addExpr(getTLSGetOffset(MF->getContext())) 326 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD)); 327 break; 328 329 case SystemZ::TLS_LDCALL: 330 LoweredMI = MCInstBuilder(SystemZ::BRASL) 331 .addReg(SystemZ::R14D) 332 .addExpr(getTLSGetOffset(MF->getContext())) 333 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM)); 334 break; 335 336 case SystemZ::GOT: 337 LoweredMI = MCInstBuilder(SystemZ::LARL) 338 .addReg(MI->getOperand(0).getReg()) 339 .addExpr(getGlobalOffsetTable(MF->getContext())); 340 break; 341 342 case SystemZ::IILF64: 343 LoweredMI = MCInstBuilder(SystemZ::IILF) 344 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 345 .addImm(MI->getOperand(2).getImm()); 346 break; 347 348 case SystemZ::IIHF64: 349 LoweredMI = MCInstBuilder(SystemZ::IIHF) 350 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 351 .addImm(MI->getOperand(2).getImm()); 352 break; 353 354 case SystemZ::RISBHH: 355 case SystemZ::RISBHL: 356 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG); 357 break; 358 359 case SystemZ::RISBLH: 360 case SystemZ::RISBLL: 361 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG); 362 break; 363 364 case SystemZ::VLVGP32: 365 LoweredMI = MCInstBuilder(SystemZ::VLVGP) 366 .addReg(MI->getOperand(0).getReg()) 367 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg())) 368 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())); 369 break; 370 371 case SystemZ::VLR32: 372 case SystemZ::VLR64: 373 LoweredMI = MCInstBuilder(SystemZ::VLR) 374 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 375 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())); 376 break; 377 378 case SystemZ::VL: 379 Lower.lower(MI, LoweredMI); 380 lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign); 381 break; 382 383 case SystemZ::VST: 384 Lower.lower(MI, LoweredMI); 385 lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign); 386 break; 387 388 case SystemZ::VLM: 389 Lower.lower(MI, LoweredMI); 390 lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign); 391 break; 392 393 case SystemZ::VSTM: 394 Lower.lower(MI, LoweredMI); 395 lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign); 396 break; 397 398 case SystemZ::VL32: 399 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF); 400 break; 401 402 case SystemZ::VL64: 403 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG); 404 break; 405 406 case SystemZ::VST32: 407 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF); 408 break; 409 410 case SystemZ::VST64: 411 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG); 412 break; 413 414 case SystemZ::LFER: 415 LoweredMI = MCInstBuilder(SystemZ::VLGVF) 416 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg())) 417 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())) 418 .addReg(0).addImm(0); 419 break; 420 421 case SystemZ::LEFR: 422 LoweredMI = MCInstBuilder(SystemZ::VLVGF) 423 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 424 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 425 .addReg(MI->getOperand(1).getReg()) 426 .addReg(0).addImm(0); 427 break; 428 429 #define LOWER_LOW(NAME) \ 430 case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break 431 432 LOWER_LOW(IILL); 433 LOWER_LOW(IILH); 434 LOWER_LOW(TMLL); 435 LOWER_LOW(TMLH); 436 LOWER_LOW(NILL); 437 LOWER_LOW(NILH); 438 LOWER_LOW(NILF); 439 LOWER_LOW(OILL); 440 LOWER_LOW(OILH); 441 LOWER_LOW(OILF); 442 LOWER_LOW(XILF); 443 444 #undef LOWER_LOW 445 446 #define LOWER_HIGH(NAME) \ 447 case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break 448 449 LOWER_HIGH(IIHL); 450 LOWER_HIGH(IIHH); 451 LOWER_HIGH(TMHL); 452 LOWER_HIGH(TMHH); 453 LOWER_HIGH(NIHL); 454 LOWER_HIGH(NIHH); 455 LOWER_HIGH(NIHF); 456 LOWER_HIGH(OIHL); 457 LOWER_HIGH(OIHH); 458 LOWER_HIGH(OIHF); 459 LOWER_HIGH(XIHF); 460 461 #undef LOWER_HIGH 462 463 case SystemZ::Serialize: 464 if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization()) 465 LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 466 .addImm(14).addReg(SystemZ::R0D); 467 else 468 LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 469 .addImm(15).addReg(SystemZ::R0D); 470 break; 471 472 // Emit nothing here but a comment if we can. 473 case SystemZ::MemBarrier: 474 OutStreamer->emitRawComment("MEMBARRIER"); 475 return; 476 477 // We want to emit "j .+2" for traps, jumping to the relative immediate field 478 // of the jump instruction, which is an illegal instruction. We cannot emit a 479 // "." symbol, so create and emit a temp label before the instruction and use 480 // that instead. 481 case SystemZ::Trap: { 482 MCSymbol *DotSym = OutContext.createTempSymbol(); 483 OutStreamer->emitLabel(DotSym); 484 485 const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 486 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 487 LoweredMI = MCInstBuilder(SystemZ::J) 488 .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 489 } 490 break; 491 492 // Conditional traps will create a branch on condition instruction that jumps 493 // to the relative immediate field of the jump instruction. (eg. "jo .+2") 494 case SystemZ::CondTrap: { 495 MCSymbol *DotSym = OutContext.createTempSymbol(); 496 OutStreamer->emitLabel(DotSym); 497 498 const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 499 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 500 LoweredMI = MCInstBuilder(SystemZ::BRC) 501 .addImm(MI->getOperand(0).getImm()) 502 .addImm(MI->getOperand(1).getImm()) 503 .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 504 } 505 break; 506 507 case TargetOpcode::FENTRY_CALL: 508 LowerFENTRY_CALL(*MI, Lower); 509 return; 510 511 case TargetOpcode::STACKMAP: 512 LowerSTACKMAP(*MI); 513 return; 514 515 case TargetOpcode::PATCHPOINT: 516 LowerPATCHPOINT(*MI, Lower); 517 return; 518 519 default: 520 Lower.lower(MI, LoweredMI); 521 break; 522 } 523 EmitToStreamer(*OutStreamer, LoweredMI); 524 } 525 526 // Emit the largest nop instruction smaller than or equal to NumBytes 527 // bytes. Return the size of nop emitted. 528 static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, 529 unsigned NumBytes, const MCSubtargetInfo &STI) { 530 if (NumBytes < 2) { 531 llvm_unreachable("Zero nops?"); 532 return 0; 533 } 534 else if (NumBytes < 4) { 535 OutStreamer.emitInstruction( 536 MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI); 537 return 2; 538 } 539 else if (NumBytes < 6) { 540 OutStreamer.emitInstruction( 541 MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0), 542 STI); 543 return 4; 544 } 545 else { 546 MCSymbol *DotSym = OutContext.createTempSymbol(); 547 const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 548 OutStreamer.emitLabel(DotSym); 549 OutStreamer.emitInstruction( 550 MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI); 551 return 6; 552 } 553 } 554 555 void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI, 556 SystemZMCInstLower &Lower) { 557 MCContext &Ctx = MF->getContext(); 558 if (MF->getFunction().hasFnAttribute("mrecord-mcount")) { 559 MCSymbol *DotSym = OutContext.createTempSymbol(); 560 OutStreamer->PushSection(); 561 OutStreamer->SwitchSection( 562 Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC)); 563 OutStreamer->emitSymbolValue(DotSym, 8); 564 OutStreamer->PopSection(); 565 OutStreamer->emitLabel(DotSym); 566 } 567 568 if (MF->getFunction().hasFnAttribute("mnop-mcount")) { 569 EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo()); 570 return; 571 } 572 573 MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__"); 574 const MCSymbolRefExpr *Op = 575 MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx); 576 OutStreamer->emitInstruction( 577 MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op), 578 getSubtargetInfo()); 579 } 580 581 void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) { 582 const SystemZInstrInfo *TII = 583 static_cast<const SystemZInstrInfo *>(MF->getSubtarget().getInstrInfo()); 584 585 unsigned NumNOPBytes = MI.getOperand(1).getImm(); 586 587 auto &Ctx = OutStreamer->getContext(); 588 MCSymbol *MILabel = Ctx.createTempSymbol(); 589 OutStreamer->emitLabel(MILabel); 590 591 SM.recordStackMap(*MILabel, MI); 592 assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!"); 593 594 // Scan ahead to trim the shadow. 595 unsigned ShadowBytes = 0; 596 const MachineBasicBlock &MBB = *MI.getParent(); 597 MachineBasicBlock::const_iterator MII(MI); 598 ++MII; 599 while (ShadowBytes < NumNOPBytes) { 600 if (MII == MBB.end() || 601 MII->getOpcode() == TargetOpcode::PATCHPOINT || 602 MII->getOpcode() == TargetOpcode::STACKMAP) 603 break; 604 ShadowBytes += TII->getInstSizeInBytes(*MII); 605 if (MII->isCall()) 606 break; 607 ++MII; 608 } 609 610 // Emit nops. 611 while (ShadowBytes < NumNOPBytes) 612 ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes, 613 getSubtargetInfo()); 614 } 615 616 // Lower a patchpoint of the form: 617 // [<def>], <id>, <numBytes>, <target>, <numArgs> 618 void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI, 619 SystemZMCInstLower &Lower) { 620 auto &Ctx = OutStreamer->getContext(); 621 MCSymbol *MILabel = Ctx.createTempSymbol(); 622 OutStreamer->emitLabel(MILabel); 623 624 SM.recordPatchPoint(*MILabel, MI); 625 PatchPointOpers Opers(&MI); 626 627 unsigned EncodedBytes = 0; 628 const MachineOperand &CalleeMO = Opers.getCallTarget(); 629 630 if (CalleeMO.isImm()) { 631 uint64_t CallTarget = CalleeMO.getImm(); 632 if (CallTarget) { 633 unsigned ScratchIdx = -1; 634 unsigned ScratchReg = 0; 635 do { 636 ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1); 637 ScratchReg = MI.getOperand(ScratchIdx).getReg(); 638 } while (ScratchReg == SystemZ::R0D); 639 640 // Materialize the call target address 641 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF) 642 .addReg(ScratchReg) 643 .addImm(CallTarget & 0xFFFFFFFF)); 644 EncodedBytes += 6; 645 if (CallTarget >> 32) { 646 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF) 647 .addReg(ScratchReg) 648 .addImm(CallTarget >> 32)); 649 EncodedBytes += 6; 650 } 651 652 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 653 .addReg(SystemZ::R14D) 654 .addReg(ScratchReg)); 655 EncodedBytes += 2; 656 } 657 } else if (CalleeMO.isGlobal()) { 658 const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT); 659 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL) 660 .addReg(SystemZ::R14D) 661 .addExpr(Expr)); 662 EncodedBytes += 6; 663 } 664 665 // Emit padding. 666 unsigned NumBytes = Opers.getNumPatchBytes(); 667 assert(NumBytes >= EncodedBytes && 668 "Patchpoint can't request size less than the length of a call."); 669 assert((NumBytes - EncodedBytes) % 2 == 0 && 670 "Invalid number of NOP bytes requested!"); 671 while (EncodedBytes < NumBytes) 672 EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes, 673 getSubtargetInfo()); 674 } 675 676 // Convert a SystemZ-specific constant pool modifier into the associated 677 // MCSymbolRefExpr variant kind. 678 static MCSymbolRefExpr::VariantKind 679 getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { 680 switch (Modifier) { 681 case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD; 682 case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM; 683 case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF; 684 case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF; 685 } 686 llvm_unreachable("Invalid SystemCPModifier!"); 687 } 688 689 void SystemZAsmPrinter::emitMachineConstantPoolValue( 690 MachineConstantPoolValue *MCPV) { 691 auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV); 692 693 const MCExpr *Expr = 694 MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()), 695 getModifierVariantKind(ZCPV->getModifier()), 696 OutContext); 697 uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType()); 698 699 OutStreamer->emitValue(Expr, Size); 700 } 701 702 bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 703 const char *ExtraCode, 704 raw_ostream &OS) { 705 if (ExtraCode) 706 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS); 707 SystemZMCInstLower Lower(MF->getContext(), *this); 708 MCOperand MO(Lower.lowerOperand(MI->getOperand(OpNo))); 709 SystemZInstPrinter::printOperand(MO, MAI, OS); 710 return false; 711 } 712 713 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 714 unsigned OpNo, 715 const char *ExtraCode, 716 raw_ostream &OS) { 717 SystemZInstPrinter::printAddress(MI->getOperand(OpNo).getReg(), 718 MI->getOperand(OpNo + 1).getImm(), 719 MI->getOperand(OpNo + 2).getReg(), OS); 720 return false; 721 } 722 723 void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) { 724 emitStackMaps(SM); 725 } 726 727 // Force static initialization. 728 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() { 729 RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget()); 730 } 731