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/MC/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 // The XPLINK ABI requires that a no-op encoding the call type is emitted after 128 // each call to a subroutine. This information can be used by the called 129 // function to determine its entry point, e.g. for generating a backtrace. The 130 // call type is encoded as a register number in the bcr instruction. See 131 // enumeration CallType for the possible values. 132 void SystemZAsmPrinter::emitCallInformation(CallType CT) { 133 EmitToStreamer(*OutStreamer, 134 MCInstBuilder(SystemZ::BCRAsm) 135 .addImm(0) 136 .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)])); 137 } 138 139 void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { 140 SystemZMCInstLower Lower(MF->getContext(), *this); 141 MCInst LoweredMI; 142 switch (MI->getOpcode()) { 143 case SystemZ::Return: 144 LoweredMI = MCInstBuilder(SystemZ::BR) 145 .addReg(SystemZ::R14D); 146 break; 147 148 case SystemZ::Return_XPLINK: 149 LoweredMI = MCInstBuilder(SystemZ::B) 150 .addReg(SystemZ::R7D) 151 .addImm(2) 152 .addReg(0); 153 break; 154 155 case SystemZ::CondReturn: 156 LoweredMI = MCInstBuilder(SystemZ::BCR) 157 .addImm(MI->getOperand(0).getImm()) 158 .addImm(MI->getOperand(1).getImm()) 159 .addReg(SystemZ::R14D); 160 break; 161 162 case SystemZ::CondReturn_XPLINK: 163 LoweredMI = MCInstBuilder(SystemZ::BC) 164 .addImm(MI->getOperand(0).getImm()) 165 .addImm(MI->getOperand(1).getImm()) 166 .addReg(SystemZ::R7D) 167 .addImm(2) 168 .addReg(0); 169 break; 170 171 case SystemZ::CRBReturn: 172 LoweredMI = MCInstBuilder(SystemZ::CRB) 173 .addReg(MI->getOperand(0).getReg()) 174 .addReg(MI->getOperand(1).getReg()) 175 .addImm(MI->getOperand(2).getImm()) 176 .addReg(SystemZ::R14D) 177 .addImm(0); 178 break; 179 180 case SystemZ::CGRBReturn: 181 LoweredMI = MCInstBuilder(SystemZ::CGRB) 182 .addReg(MI->getOperand(0).getReg()) 183 .addReg(MI->getOperand(1).getReg()) 184 .addImm(MI->getOperand(2).getImm()) 185 .addReg(SystemZ::R14D) 186 .addImm(0); 187 break; 188 189 case SystemZ::CIBReturn: 190 LoweredMI = MCInstBuilder(SystemZ::CIB) 191 .addReg(MI->getOperand(0).getReg()) 192 .addImm(MI->getOperand(1).getImm()) 193 .addImm(MI->getOperand(2).getImm()) 194 .addReg(SystemZ::R14D) 195 .addImm(0); 196 break; 197 198 case SystemZ::CGIBReturn: 199 LoweredMI = MCInstBuilder(SystemZ::CGIB) 200 .addReg(MI->getOperand(0).getReg()) 201 .addImm(MI->getOperand(1).getImm()) 202 .addImm(MI->getOperand(2).getImm()) 203 .addReg(SystemZ::R14D) 204 .addImm(0); 205 break; 206 207 case SystemZ::CLRBReturn: 208 LoweredMI = MCInstBuilder(SystemZ::CLRB) 209 .addReg(MI->getOperand(0).getReg()) 210 .addReg(MI->getOperand(1).getReg()) 211 .addImm(MI->getOperand(2).getImm()) 212 .addReg(SystemZ::R14D) 213 .addImm(0); 214 break; 215 216 case SystemZ::CLGRBReturn: 217 LoweredMI = MCInstBuilder(SystemZ::CLGRB) 218 .addReg(MI->getOperand(0).getReg()) 219 .addReg(MI->getOperand(1).getReg()) 220 .addImm(MI->getOperand(2).getImm()) 221 .addReg(SystemZ::R14D) 222 .addImm(0); 223 break; 224 225 case SystemZ::CLIBReturn: 226 LoweredMI = MCInstBuilder(SystemZ::CLIB) 227 .addReg(MI->getOperand(0).getReg()) 228 .addImm(MI->getOperand(1).getImm()) 229 .addImm(MI->getOperand(2).getImm()) 230 .addReg(SystemZ::R14D) 231 .addImm(0); 232 break; 233 234 case SystemZ::CLGIBReturn: 235 LoweredMI = MCInstBuilder(SystemZ::CLGIB) 236 .addReg(MI->getOperand(0).getReg()) 237 .addImm(MI->getOperand(1).getImm()) 238 .addImm(MI->getOperand(2).getImm()) 239 .addReg(SystemZ::R14D) 240 .addImm(0); 241 break; 242 243 case SystemZ::CallBRASL_XPLINK64: 244 EmitToStreamer(*OutStreamer, 245 MCInstBuilder(SystemZ::BRASL) 246 .addReg(SystemZ::R7D) 247 .addExpr(Lower.getExpr(MI->getOperand(0), 248 MCSymbolRefExpr::VK_PLT))); 249 emitCallInformation(CallType::BRASL7); 250 return; 251 252 case SystemZ::CallBASR_XPLINK64: 253 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 254 .addReg(SystemZ::R7D) 255 .addReg(MI->getOperand(0).getReg())); 256 emitCallInformation(CallType::BASR76); 257 return; 258 259 case SystemZ::CallBRASL: 260 LoweredMI = MCInstBuilder(SystemZ::BRASL) 261 .addReg(SystemZ::R14D) 262 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 263 break; 264 265 case SystemZ::CallBASR: 266 LoweredMI = MCInstBuilder(SystemZ::BASR) 267 .addReg(SystemZ::R14D) 268 .addReg(MI->getOperand(0).getReg()); 269 break; 270 271 case SystemZ::CallJG: 272 LoweredMI = MCInstBuilder(SystemZ::JG) 273 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 274 break; 275 276 case SystemZ::CallBRCL: 277 LoweredMI = MCInstBuilder(SystemZ::BRCL) 278 .addImm(MI->getOperand(0).getImm()) 279 .addImm(MI->getOperand(1).getImm()) 280 .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT)); 281 break; 282 283 case SystemZ::CallBR: 284 LoweredMI = MCInstBuilder(SystemZ::BR) 285 .addReg(MI->getOperand(0).getReg()); 286 break; 287 288 case SystemZ::CallBCR: 289 LoweredMI = MCInstBuilder(SystemZ::BCR) 290 .addImm(MI->getOperand(0).getImm()) 291 .addImm(MI->getOperand(1).getImm()) 292 .addReg(MI->getOperand(2).getReg()); 293 break; 294 295 case SystemZ::CRBCall: 296 LoweredMI = MCInstBuilder(SystemZ::CRB) 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::CGRBCall: 305 LoweredMI = MCInstBuilder(SystemZ::CGRB) 306 .addReg(MI->getOperand(0).getReg()) 307 .addReg(MI->getOperand(1).getReg()) 308 .addImm(MI->getOperand(2).getImm()) 309 .addReg(MI->getOperand(3).getReg()) 310 .addImm(0); 311 break; 312 313 case SystemZ::CIBCall: 314 LoweredMI = MCInstBuilder(SystemZ::CIB) 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::CGIBCall: 323 LoweredMI = MCInstBuilder(SystemZ::CGIB) 324 .addReg(MI->getOperand(0).getReg()) 325 .addImm(MI->getOperand(1).getImm()) 326 .addImm(MI->getOperand(2).getImm()) 327 .addReg(MI->getOperand(3).getReg()) 328 .addImm(0); 329 break; 330 331 case SystemZ::CLRBCall: 332 LoweredMI = MCInstBuilder(SystemZ::CLRB) 333 .addReg(MI->getOperand(0).getReg()) 334 .addReg(MI->getOperand(1).getReg()) 335 .addImm(MI->getOperand(2).getImm()) 336 .addReg(MI->getOperand(3).getReg()) 337 .addImm(0); 338 break; 339 340 case SystemZ::CLGRBCall: 341 LoweredMI = MCInstBuilder(SystemZ::CLGRB) 342 .addReg(MI->getOperand(0).getReg()) 343 .addReg(MI->getOperand(1).getReg()) 344 .addImm(MI->getOperand(2).getImm()) 345 .addReg(MI->getOperand(3).getReg()) 346 .addImm(0); 347 break; 348 349 case SystemZ::CLIBCall: 350 LoweredMI = MCInstBuilder(SystemZ::CLIB) 351 .addReg(MI->getOperand(0).getReg()) 352 .addImm(MI->getOperand(1).getImm()) 353 .addImm(MI->getOperand(2).getImm()) 354 .addReg(MI->getOperand(3).getReg()) 355 .addImm(0); 356 break; 357 358 case SystemZ::CLGIBCall: 359 LoweredMI = MCInstBuilder(SystemZ::CLGIB) 360 .addReg(MI->getOperand(0).getReg()) 361 .addImm(MI->getOperand(1).getImm()) 362 .addImm(MI->getOperand(2).getImm()) 363 .addReg(MI->getOperand(3).getReg()) 364 .addImm(0); 365 break; 366 367 case SystemZ::TLS_GDCALL: 368 LoweredMI = MCInstBuilder(SystemZ::BRASL) 369 .addReg(SystemZ::R14D) 370 .addExpr(getTLSGetOffset(MF->getContext())) 371 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD)); 372 break; 373 374 case SystemZ::TLS_LDCALL: 375 LoweredMI = MCInstBuilder(SystemZ::BRASL) 376 .addReg(SystemZ::R14D) 377 .addExpr(getTLSGetOffset(MF->getContext())) 378 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM)); 379 break; 380 381 case SystemZ::GOT: 382 LoweredMI = MCInstBuilder(SystemZ::LARL) 383 .addReg(MI->getOperand(0).getReg()) 384 .addExpr(getGlobalOffsetTable(MF->getContext())); 385 break; 386 387 case SystemZ::IILF64: 388 LoweredMI = MCInstBuilder(SystemZ::IILF) 389 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 390 .addImm(MI->getOperand(2).getImm()); 391 break; 392 393 case SystemZ::IIHF64: 394 LoweredMI = MCInstBuilder(SystemZ::IIHF) 395 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 396 .addImm(MI->getOperand(2).getImm()); 397 break; 398 399 case SystemZ::RISBHH: 400 case SystemZ::RISBHL: 401 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG); 402 break; 403 404 case SystemZ::RISBLH: 405 case SystemZ::RISBLL: 406 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG); 407 break; 408 409 case SystemZ::VLVGP32: 410 LoweredMI = MCInstBuilder(SystemZ::VLVGP) 411 .addReg(MI->getOperand(0).getReg()) 412 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg())) 413 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())); 414 break; 415 416 case SystemZ::VLR32: 417 case SystemZ::VLR64: 418 LoweredMI = MCInstBuilder(SystemZ::VLR) 419 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 420 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())); 421 break; 422 423 case SystemZ::VL: 424 Lower.lower(MI, LoweredMI); 425 lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign); 426 break; 427 428 case SystemZ::VST: 429 Lower.lower(MI, LoweredMI); 430 lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign); 431 break; 432 433 case SystemZ::VLM: 434 Lower.lower(MI, LoweredMI); 435 lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign); 436 break; 437 438 case SystemZ::VSTM: 439 Lower.lower(MI, LoweredMI); 440 lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign); 441 break; 442 443 case SystemZ::VL32: 444 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF); 445 break; 446 447 case SystemZ::VL64: 448 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG); 449 break; 450 451 case SystemZ::VST32: 452 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF); 453 break; 454 455 case SystemZ::VST64: 456 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG); 457 break; 458 459 case SystemZ::LFER: 460 LoweredMI = MCInstBuilder(SystemZ::VLGVF) 461 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg())) 462 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())) 463 .addReg(0).addImm(0); 464 break; 465 466 case SystemZ::LEFR: 467 LoweredMI = MCInstBuilder(SystemZ::VLVGF) 468 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 469 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 470 .addReg(MI->getOperand(1).getReg()) 471 .addReg(0).addImm(0); 472 break; 473 474 #define LOWER_LOW(NAME) \ 475 case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break 476 477 LOWER_LOW(IILL); 478 LOWER_LOW(IILH); 479 LOWER_LOW(TMLL); 480 LOWER_LOW(TMLH); 481 LOWER_LOW(NILL); 482 LOWER_LOW(NILH); 483 LOWER_LOW(NILF); 484 LOWER_LOW(OILL); 485 LOWER_LOW(OILH); 486 LOWER_LOW(OILF); 487 LOWER_LOW(XILF); 488 489 #undef LOWER_LOW 490 491 #define LOWER_HIGH(NAME) \ 492 case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break 493 494 LOWER_HIGH(IIHL); 495 LOWER_HIGH(IIHH); 496 LOWER_HIGH(TMHL); 497 LOWER_HIGH(TMHH); 498 LOWER_HIGH(NIHL); 499 LOWER_HIGH(NIHH); 500 LOWER_HIGH(NIHF); 501 LOWER_HIGH(OIHL); 502 LOWER_HIGH(OIHH); 503 LOWER_HIGH(OIHF); 504 LOWER_HIGH(XIHF); 505 506 #undef LOWER_HIGH 507 508 case SystemZ::Serialize: 509 if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization()) 510 LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 511 .addImm(14).addReg(SystemZ::R0D); 512 else 513 LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 514 .addImm(15).addReg(SystemZ::R0D); 515 break; 516 517 // Emit nothing here but a comment if we can. 518 case SystemZ::MemBarrier: 519 OutStreamer->emitRawComment("MEMBARRIER"); 520 return; 521 522 // We want to emit "j .+2" for traps, jumping to the relative immediate field 523 // of the jump instruction, which is an illegal instruction. We cannot emit a 524 // "." symbol, so create and emit a temp label before the instruction and use 525 // that instead. 526 case SystemZ::Trap: { 527 MCSymbol *DotSym = OutContext.createTempSymbol(); 528 OutStreamer->emitLabel(DotSym); 529 530 const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 531 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 532 LoweredMI = MCInstBuilder(SystemZ::J) 533 .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 534 } 535 break; 536 537 // Conditional traps will create a branch on condition instruction that jumps 538 // to the relative immediate field of the jump instruction. (eg. "jo .+2") 539 case SystemZ::CondTrap: { 540 MCSymbol *DotSym = OutContext.createTempSymbol(); 541 OutStreamer->emitLabel(DotSym); 542 543 const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 544 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 545 LoweredMI = MCInstBuilder(SystemZ::BRC) 546 .addImm(MI->getOperand(0).getImm()) 547 .addImm(MI->getOperand(1).getImm()) 548 .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 549 } 550 break; 551 552 case TargetOpcode::FENTRY_CALL: 553 LowerFENTRY_CALL(*MI, Lower); 554 return; 555 556 case TargetOpcode::STACKMAP: 557 LowerSTACKMAP(*MI); 558 return; 559 560 case TargetOpcode::PATCHPOINT: 561 LowerPATCHPOINT(*MI, Lower); 562 return; 563 564 case SystemZ::EXRL_Pseudo: { 565 unsigned TargetInsOpc = MI->getOperand(0).getImm(); 566 Register LenMinus1Reg = MI->getOperand(1).getReg(); 567 Register DestReg = MI->getOperand(2).getReg(); 568 int64_t DestDisp = MI->getOperand(3).getImm(); 569 Register SrcReg = MI->getOperand(4).getReg(); 570 int64_t SrcDisp = MI->getOperand(5).getImm(); 571 572 SystemZTargetStreamer *TS = getTargetStreamer(); 573 MCSymbol *DotSym = nullptr; 574 MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg) 575 .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp); 576 SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget()); 577 SystemZTargetStreamer::EXRLT2SymMap::iterator I = 578 TS->EXRLTargets2Sym.find(ET_STI); 579 if (I != TS->EXRLTargets2Sym.end()) 580 DotSym = I->second; 581 else 582 TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol(); 583 const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 584 EmitToStreamer( 585 *OutStreamer, 586 MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot)); 587 return; 588 } 589 590 default: 591 Lower.lower(MI, LoweredMI); 592 break; 593 } 594 EmitToStreamer(*OutStreamer, LoweredMI); 595 } 596 597 // Emit the largest nop instruction smaller than or equal to NumBytes 598 // bytes. Return the size of nop emitted. 599 static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, 600 unsigned NumBytes, const MCSubtargetInfo &STI) { 601 if (NumBytes < 2) { 602 llvm_unreachable("Zero nops?"); 603 return 0; 604 } 605 else if (NumBytes < 4) { 606 OutStreamer.emitInstruction( 607 MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI); 608 return 2; 609 } 610 else if (NumBytes < 6) { 611 OutStreamer.emitInstruction( 612 MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0), 613 STI); 614 return 4; 615 } 616 else { 617 MCSymbol *DotSym = OutContext.createTempSymbol(); 618 const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 619 OutStreamer.emitLabel(DotSym); 620 OutStreamer.emitInstruction( 621 MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI); 622 return 6; 623 } 624 } 625 626 void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI, 627 SystemZMCInstLower &Lower) { 628 MCContext &Ctx = MF->getContext(); 629 if (MF->getFunction().hasFnAttribute("mrecord-mcount")) { 630 MCSymbol *DotSym = OutContext.createTempSymbol(); 631 OutStreamer->PushSection(); 632 OutStreamer->SwitchSection( 633 Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC)); 634 OutStreamer->emitSymbolValue(DotSym, 8); 635 OutStreamer->PopSection(); 636 OutStreamer->emitLabel(DotSym); 637 } 638 639 if (MF->getFunction().hasFnAttribute("mnop-mcount")) { 640 EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo()); 641 return; 642 } 643 644 MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__"); 645 const MCSymbolRefExpr *Op = 646 MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx); 647 OutStreamer->emitInstruction( 648 MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op), 649 getSubtargetInfo()); 650 } 651 652 void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) { 653 const SystemZInstrInfo *TII = 654 static_cast<const SystemZInstrInfo *>(MF->getSubtarget().getInstrInfo()); 655 656 unsigned NumNOPBytes = MI.getOperand(1).getImm(); 657 658 auto &Ctx = OutStreamer->getContext(); 659 MCSymbol *MILabel = Ctx.createTempSymbol(); 660 OutStreamer->emitLabel(MILabel); 661 662 SM.recordStackMap(*MILabel, MI); 663 assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!"); 664 665 // Scan ahead to trim the shadow. 666 unsigned ShadowBytes = 0; 667 const MachineBasicBlock &MBB = *MI.getParent(); 668 MachineBasicBlock::const_iterator MII(MI); 669 ++MII; 670 while (ShadowBytes < NumNOPBytes) { 671 if (MII == MBB.end() || 672 MII->getOpcode() == TargetOpcode::PATCHPOINT || 673 MII->getOpcode() == TargetOpcode::STACKMAP) 674 break; 675 ShadowBytes += TII->getInstSizeInBytes(*MII); 676 if (MII->isCall()) 677 break; 678 ++MII; 679 } 680 681 // Emit nops. 682 while (ShadowBytes < NumNOPBytes) 683 ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes, 684 getSubtargetInfo()); 685 } 686 687 // Lower a patchpoint of the form: 688 // [<def>], <id>, <numBytes>, <target>, <numArgs> 689 void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI, 690 SystemZMCInstLower &Lower) { 691 auto &Ctx = OutStreamer->getContext(); 692 MCSymbol *MILabel = Ctx.createTempSymbol(); 693 OutStreamer->emitLabel(MILabel); 694 695 SM.recordPatchPoint(*MILabel, MI); 696 PatchPointOpers Opers(&MI); 697 698 unsigned EncodedBytes = 0; 699 const MachineOperand &CalleeMO = Opers.getCallTarget(); 700 701 if (CalleeMO.isImm()) { 702 uint64_t CallTarget = CalleeMO.getImm(); 703 if (CallTarget) { 704 unsigned ScratchIdx = -1; 705 unsigned ScratchReg = 0; 706 do { 707 ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1); 708 ScratchReg = MI.getOperand(ScratchIdx).getReg(); 709 } while (ScratchReg == SystemZ::R0D); 710 711 // Materialize the call target address 712 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF) 713 .addReg(ScratchReg) 714 .addImm(CallTarget & 0xFFFFFFFF)); 715 EncodedBytes += 6; 716 if (CallTarget >> 32) { 717 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF) 718 .addReg(ScratchReg) 719 .addImm(CallTarget >> 32)); 720 EncodedBytes += 6; 721 } 722 723 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 724 .addReg(SystemZ::R14D) 725 .addReg(ScratchReg)); 726 EncodedBytes += 2; 727 } 728 } else if (CalleeMO.isGlobal()) { 729 const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT); 730 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL) 731 .addReg(SystemZ::R14D) 732 .addExpr(Expr)); 733 EncodedBytes += 6; 734 } 735 736 // Emit padding. 737 unsigned NumBytes = Opers.getNumPatchBytes(); 738 assert(NumBytes >= EncodedBytes && 739 "Patchpoint can't request size less than the length of a call."); 740 assert((NumBytes - EncodedBytes) % 2 == 0 && 741 "Invalid number of NOP bytes requested!"); 742 while (EncodedBytes < NumBytes) 743 EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes, 744 getSubtargetInfo()); 745 } 746 747 // Convert a SystemZ-specific constant pool modifier into the associated 748 // MCSymbolRefExpr variant kind. 749 static MCSymbolRefExpr::VariantKind 750 getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { 751 switch (Modifier) { 752 case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD; 753 case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM; 754 case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF; 755 case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF; 756 } 757 llvm_unreachable("Invalid SystemCPModifier!"); 758 } 759 760 void SystemZAsmPrinter::emitMachineConstantPoolValue( 761 MachineConstantPoolValue *MCPV) { 762 auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV); 763 764 const MCExpr *Expr = 765 MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()), 766 getModifierVariantKind(ZCPV->getModifier()), 767 OutContext); 768 uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType()); 769 770 OutStreamer->emitValue(Expr, Size); 771 } 772 773 bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 774 const char *ExtraCode, 775 raw_ostream &OS) { 776 const MCRegisterInfo &MRI = *TM.getMCRegisterInfo(); 777 const MachineOperand &MO = MI->getOperand(OpNo); 778 MCOperand MCOp; 779 if (ExtraCode) { 780 if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() && 781 SystemZ::GR128BitRegClass.contains(MO.getReg())) 782 MCOp = 783 MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64)); 784 else 785 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS); 786 } else { 787 SystemZMCInstLower Lower(MF->getContext(), *this); 788 MCOp = Lower.lowerOperand(MO); 789 } 790 SystemZInstPrinter::printOperand(MCOp, MAI, OS); 791 return false; 792 } 793 794 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 795 unsigned OpNo, 796 const char *ExtraCode, 797 raw_ostream &OS) { 798 SystemZInstPrinter:: 799 printAddress(MAI, MI->getOperand(OpNo).getReg(), 800 MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()), 801 MI->getOperand(OpNo + 2).getReg(), OS); 802 return false; 803 } 804 805 void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) { 806 emitStackMaps(SM); 807 } 808 809 void SystemZAsmPrinter::emitFunctionEntryLabel() { 810 const SystemZSubtarget &Subtarget = 811 static_cast<const SystemZSubtarget &>(MF->getSubtarget()); 812 813 if (Subtarget.getTargetTriple().isOSzOS()) { 814 MCContext &OutContext = OutStreamer->getContext(); 815 MCSymbol *EPMarkerSym = OutContext.createTempSymbol("CM_", true); 816 817 // EntryPoint Marker 818 const MachineFrameInfo &MFFrame = MF->getFrameInfo(); 819 bool IsUsingAlloca = MFFrame.hasVarSizedObjects(); 820 821 // Set Flags 822 uint8_t Flags = 0; 823 if (IsUsingAlloca) 824 Flags |= 0x04; 825 826 uint32_t DSASize = MFFrame.getStackSize(); 827 828 // Combine into top 27 bits of DSASize and bottom 5 bits of Flags. 829 uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5 830 DSAAndFlags |= Flags; 831 832 // Emit entry point marker section. 833 OutStreamer->AddComment("XPLINK Routine Layout Entry"); 834 OutStreamer->emitLabel(EPMarkerSym); 835 OutStreamer->AddComment("Eyecatcher 0x00C300C500C500"); 836 OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher. 837 OutStreamer->AddComment("Mark Type C'1'"); 838 OutStreamer->emitInt8(0xF1); // Mark Type. 839 if (OutStreamer->isVerboseAsm()) { 840 OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize)); 841 OutStreamer->AddComment("Entry Flags"); 842 if (Flags & 0x04) 843 OutStreamer->AddComment(" Bit 2: 1 = Uses alloca"); 844 else 845 OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca"); 846 } 847 OutStreamer->emitInt32(DSAAndFlags); 848 } 849 850 AsmPrinter::emitFunctionEntryLabel(); 851 } 852 853 // Force static initialization. 854 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() { 855 RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget()); 856 } 857