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