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