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