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