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/ADT/StringExtras.h" 20 #include "llvm/BinaryFormat/ELF.h" 21 #include "llvm/CodeGen/MachineModuleInfoImpls.h" 22 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 23 #include "llvm/IR/Mangler.h" 24 #include "llvm/MC/MCExpr.h" 25 #include "llvm/MC/MCInstBuilder.h" 26 #include "llvm/MC/MCSectionELF.h" 27 #include "llvm/MC/MCStreamer.h" 28 #include "llvm/MC/TargetRegistry.h" 29 30 using namespace llvm; 31 32 // Return an RI instruction like MI with opcode Opcode, but with the 33 // GR64 register operands turned into GR32s. 34 static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) { 35 if (MI->isCompare()) 36 return MCInstBuilder(Opcode) 37 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 38 .addImm(MI->getOperand(1).getImm()); 39 else 40 return MCInstBuilder(Opcode) 41 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 42 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg())) 43 .addImm(MI->getOperand(2).getImm()); 44 } 45 46 // Return an RI instruction like MI with opcode Opcode, but with the 47 // GR64 register operands turned into GRH32s. 48 static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) { 49 if (MI->isCompare()) 50 return MCInstBuilder(Opcode) 51 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 52 .addImm(MI->getOperand(1).getImm()); 53 else 54 return MCInstBuilder(Opcode) 55 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 56 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg())) 57 .addImm(MI->getOperand(2).getImm()); 58 } 59 60 // Return an RI instruction like MI with opcode Opcode, but with the 61 // R2 register turned into a GR64. 62 static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) { 63 return MCInstBuilder(Opcode) 64 .addReg(MI->getOperand(0).getReg()) 65 .addReg(MI->getOperand(1).getReg()) 66 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())) 67 .addImm(MI->getOperand(3).getImm()) 68 .addImm(MI->getOperand(4).getImm()) 69 .addImm(MI->getOperand(5).getImm()); 70 } 71 72 static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) { 73 StringRef Name = "__tls_get_offset"; 74 return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name), 75 MCSymbolRefExpr::VK_PLT, 76 Context); 77 } 78 79 static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) { 80 StringRef Name = "_GLOBAL_OFFSET_TABLE_"; 81 return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name), 82 MCSymbolRefExpr::VK_None, 83 Context); 84 } 85 86 // MI is an instruction that accepts an optional alignment hint, 87 // and which was already lowered to LoweredMI. If the alignment 88 // of the original memory operand is known, update LoweredMI to 89 // an instruction with the corresponding hint set. 90 static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI, 91 unsigned Opcode) { 92 if (MI->memoperands_empty()) 93 return; 94 95 Align Alignment = Align(16); 96 for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(), 97 EE = MI->memoperands_end(); MMOI != EE; ++MMOI) 98 if ((*MMOI)->getAlign() < Alignment) 99 Alignment = (*MMOI)->getAlign(); 100 101 unsigned AlignmentHint = 0; 102 if (Alignment >= Align(16)) 103 AlignmentHint = 4; 104 else if (Alignment >= Align(8)) 105 AlignmentHint = 3; 106 if (AlignmentHint == 0) 107 return; 108 109 LoweredMI.setOpcode(Opcode); 110 LoweredMI.addOperand(MCOperand::createImm(AlignmentHint)); 111 } 112 113 // MI loads the high part of a vector from memory. Return an instruction 114 // that uses replicating vector load Opcode to do the same thing. 115 static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) { 116 return MCInstBuilder(Opcode) 117 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 118 .addReg(MI->getOperand(1).getReg()) 119 .addImm(MI->getOperand(2).getImm()) 120 .addReg(MI->getOperand(3).getReg()); 121 } 122 123 // MI stores the high part of a vector to memory. Return an instruction 124 // that uses elemental vector store Opcode to do the same thing. 125 static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) { 126 return MCInstBuilder(Opcode) 127 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 128 .addReg(MI->getOperand(1).getReg()) 129 .addImm(MI->getOperand(2).getImm()) 130 .addReg(MI->getOperand(3).getReg()) 131 .addImm(0); 132 } 133 134 // The XPLINK ABI requires that a no-op encoding the call type is emitted after 135 // each call to a subroutine. This information can be used by the called 136 // function to determine its entry point, e.g. for generating a backtrace. The 137 // call type is encoded as a register number in the bcr instruction. See 138 // enumeration CallType for the possible values. 139 void SystemZAsmPrinter::emitCallInformation(CallType CT) { 140 EmitToStreamer(*OutStreamer, 141 MCInstBuilder(SystemZ::BCRAsm) 142 .addImm(0) 143 .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)])); 144 } 145 146 void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { 147 SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(), 148 getSubtargetInfo().getFeatureBits()); 149 150 SystemZMCInstLower Lower(MF->getContext(), *this); 151 MCInst LoweredMI; 152 switch (MI->getOpcode()) { 153 case SystemZ::Return: 154 LoweredMI = MCInstBuilder(SystemZ::BR) 155 .addReg(SystemZ::R14D); 156 break; 157 158 case SystemZ::Return_XPLINK: 159 LoweredMI = MCInstBuilder(SystemZ::B) 160 .addReg(SystemZ::R7D) 161 .addImm(2) 162 .addReg(0); 163 break; 164 165 case SystemZ::CondReturn: 166 LoweredMI = MCInstBuilder(SystemZ::BCR) 167 .addImm(MI->getOperand(0).getImm()) 168 .addImm(MI->getOperand(1).getImm()) 169 .addReg(SystemZ::R14D); 170 break; 171 172 case SystemZ::CondReturn_XPLINK: 173 LoweredMI = MCInstBuilder(SystemZ::BC) 174 .addImm(MI->getOperand(0).getImm()) 175 .addImm(MI->getOperand(1).getImm()) 176 .addReg(SystemZ::R7D) 177 .addImm(2) 178 .addReg(0); 179 break; 180 181 case SystemZ::CRBReturn: 182 LoweredMI = MCInstBuilder(SystemZ::CRB) 183 .addReg(MI->getOperand(0).getReg()) 184 .addReg(MI->getOperand(1).getReg()) 185 .addImm(MI->getOperand(2).getImm()) 186 .addReg(SystemZ::R14D) 187 .addImm(0); 188 break; 189 190 case SystemZ::CGRBReturn: 191 LoweredMI = MCInstBuilder(SystemZ::CGRB) 192 .addReg(MI->getOperand(0).getReg()) 193 .addReg(MI->getOperand(1).getReg()) 194 .addImm(MI->getOperand(2).getImm()) 195 .addReg(SystemZ::R14D) 196 .addImm(0); 197 break; 198 199 case SystemZ::CIBReturn: 200 LoweredMI = MCInstBuilder(SystemZ::CIB) 201 .addReg(MI->getOperand(0).getReg()) 202 .addImm(MI->getOperand(1).getImm()) 203 .addImm(MI->getOperand(2).getImm()) 204 .addReg(SystemZ::R14D) 205 .addImm(0); 206 break; 207 208 case SystemZ::CGIBReturn: 209 LoweredMI = MCInstBuilder(SystemZ::CGIB) 210 .addReg(MI->getOperand(0).getReg()) 211 .addImm(MI->getOperand(1).getImm()) 212 .addImm(MI->getOperand(2).getImm()) 213 .addReg(SystemZ::R14D) 214 .addImm(0); 215 break; 216 217 case SystemZ::CLRBReturn: 218 LoweredMI = MCInstBuilder(SystemZ::CLRB) 219 .addReg(MI->getOperand(0).getReg()) 220 .addReg(MI->getOperand(1).getReg()) 221 .addImm(MI->getOperand(2).getImm()) 222 .addReg(SystemZ::R14D) 223 .addImm(0); 224 break; 225 226 case SystemZ::CLGRBReturn: 227 LoweredMI = MCInstBuilder(SystemZ::CLGRB) 228 .addReg(MI->getOperand(0).getReg()) 229 .addReg(MI->getOperand(1).getReg()) 230 .addImm(MI->getOperand(2).getImm()) 231 .addReg(SystemZ::R14D) 232 .addImm(0); 233 break; 234 235 case SystemZ::CLIBReturn: 236 LoweredMI = MCInstBuilder(SystemZ::CLIB) 237 .addReg(MI->getOperand(0).getReg()) 238 .addImm(MI->getOperand(1).getImm()) 239 .addImm(MI->getOperand(2).getImm()) 240 .addReg(SystemZ::R14D) 241 .addImm(0); 242 break; 243 244 case SystemZ::CLGIBReturn: 245 LoweredMI = MCInstBuilder(SystemZ::CLGIB) 246 .addReg(MI->getOperand(0).getReg()) 247 .addImm(MI->getOperand(1).getImm()) 248 .addImm(MI->getOperand(2).getImm()) 249 .addReg(SystemZ::R14D) 250 .addImm(0); 251 break; 252 253 case SystemZ::CallBRASL_XPLINK64: 254 EmitToStreamer(*OutStreamer, 255 MCInstBuilder(SystemZ::BRASL) 256 .addReg(SystemZ::R7D) 257 .addExpr(Lower.getExpr(MI->getOperand(0), 258 MCSymbolRefExpr::VK_PLT))); 259 emitCallInformation(CallType::BRASL7); 260 return; 261 262 case SystemZ::CallBASR_XPLINK64: 263 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 264 .addReg(SystemZ::R7D) 265 .addReg(MI->getOperand(0).getReg())); 266 emitCallInformation(CallType::BASR76); 267 return; 268 269 case SystemZ::CallBASR_STACKEXT: 270 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 271 .addReg(SystemZ::R3D) 272 .addReg(MI->getOperand(0).getReg())); 273 emitCallInformation(CallType::BASR33); 274 return; 275 276 case SystemZ::CallBRASL: 277 LoweredMI = MCInstBuilder(SystemZ::BRASL) 278 .addReg(SystemZ::R14D) 279 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 280 break; 281 282 case SystemZ::CallBASR: 283 LoweredMI = MCInstBuilder(SystemZ::BASR) 284 .addReg(SystemZ::R14D) 285 .addReg(MI->getOperand(0).getReg()); 286 break; 287 288 case SystemZ::CallJG: 289 LoweredMI = MCInstBuilder(SystemZ::JG) 290 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 291 break; 292 293 case SystemZ::CallBRCL: 294 LoweredMI = MCInstBuilder(SystemZ::BRCL) 295 .addImm(MI->getOperand(0).getImm()) 296 .addImm(MI->getOperand(1).getImm()) 297 .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT)); 298 break; 299 300 case SystemZ::CallBR: 301 LoweredMI = MCInstBuilder(SystemZ::BR) 302 .addReg(MI->getOperand(0).getReg()); 303 break; 304 305 case SystemZ::CallBCR: 306 LoweredMI = MCInstBuilder(SystemZ::BCR) 307 .addImm(MI->getOperand(0).getImm()) 308 .addImm(MI->getOperand(1).getImm()) 309 .addReg(MI->getOperand(2).getReg()); 310 break; 311 312 case SystemZ::CRBCall: 313 LoweredMI = MCInstBuilder(SystemZ::CRB) 314 .addReg(MI->getOperand(0).getReg()) 315 .addReg(MI->getOperand(1).getReg()) 316 .addImm(MI->getOperand(2).getImm()) 317 .addReg(MI->getOperand(3).getReg()) 318 .addImm(0); 319 break; 320 321 case SystemZ::CGRBCall: 322 LoweredMI = MCInstBuilder(SystemZ::CGRB) 323 .addReg(MI->getOperand(0).getReg()) 324 .addReg(MI->getOperand(1).getReg()) 325 .addImm(MI->getOperand(2).getImm()) 326 .addReg(MI->getOperand(3).getReg()) 327 .addImm(0); 328 break; 329 330 case SystemZ::CIBCall: 331 LoweredMI = MCInstBuilder(SystemZ::CIB) 332 .addReg(MI->getOperand(0).getReg()) 333 .addImm(MI->getOperand(1).getImm()) 334 .addImm(MI->getOperand(2).getImm()) 335 .addReg(MI->getOperand(3).getReg()) 336 .addImm(0); 337 break; 338 339 case SystemZ::CGIBCall: 340 LoweredMI = MCInstBuilder(SystemZ::CGIB) 341 .addReg(MI->getOperand(0).getReg()) 342 .addImm(MI->getOperand(1).getImm()) 343 .addImm(MI->getOperand(2).getImm()) 344 .addReg(MI->getOperand(3).getReg()) 345 .addImm(0); 346 break; 347 348 case SystemZ::CLRBCall: 349 LoweredMI = MCInstBuilder(SystemZ::CLRB) 350 .addReg(MI->getOperand(0).getReg()) 351 .addReg(MI->getOperand(1).getReg()) 352 .addImm(MI->getOperand(2).getImm()) 353 .addReg(MI->getOperand(3).getReg()) 354 .addImm(0); 355 break; 356 357 case SystemZ::CLGRBCall: 358 LoweredMI = MCInstBuilder(SystemZ::CLGRB) 359 .addReg(MI->getOperand(0).getReg()) 360 .addReg(MI->getOperand(1).getReg()) 361 .addImm(MI->getOperand(2).getImm()) 362 .addReg(MI->getOperand(3).getReg()) 363 .addImm(0); 364 break; 365 366 case SystemZ::CLIBCall: 367 LoweredMI = MCInstBuilder(SystemZ::CLIB) 368 .addReg(MI->getOperand(0).getReg()) 369 .addImm(MI->getOperand(1).getImm()) 370 .addImm(MI->getOperand(2).getImm()) 371 .addReg(MI->getOperand(3).getReg()) 372 .addImm(0); 373 break; 374 375 case SystemZ::CLGIBCall: 376 LoweredMI = MCInstBuilder(SystemZ::CLGIB) 377 .addReg(MI->getOperand(0).getReg()) 378 .addImm(MI->getOperand(1).getImm()) 379 .addImm(MI->getOperand(2).getImm()) 380 .addReg(MI->getOperand(3).getReg()) 381 .addImm(0); 382 break; 383 384 case SystemZ::TLS_GDCALL: 385 LoweredMI = MCInstBuilder(SystemZ::BRASL) 386 .addReg(SystemZ::R14D) 387 .addExpr(getTLSGetOffset(MF->getContext())) 388 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD)); 389 break; 390 391 case SystemZ::TLS_LDCALL: 392 LoweredMI = MCInstBuilder(SystemZ::BRASL) 393 .addReg(SystemZ::R14D) 394 .addExpr(getTLSGetOffset(MF->getContext())) 395 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM)); 396 break; 397 398 case SystemZ::GOT: 399 LoweredMI = MCInstBuilder(SystemZ::LARL) 400 .addReg(MI->getOperand(0).getReg()) 401 .addExpr(getGlobalOffsetTable(MF->getContext())); 402 break; 403 404 case SystemZ::IILF64: 405 LoweredMI = MCInstBuilder(SystemZ::IILF) 406 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 407 .addImm(MI->getOperand(2).getImm()); 408 break; 409 410 case SystemZ::IIHF64: 411 LoweredMI = MCInstBuilder(SystemZ::IIHF) 412 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 413 .addImm(MI->getOperand(2).getImm()); 414 break; 415 416 case SystemZ::RISBHH: 417 case SystemZ::RISBHL: 418 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG); 419 break; 420 421 case SystemZ::RISBLH: 422 case SystemZ::RISBLL: 423 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG); 424 break; 425 426 case SystemZ::VLVGP32: 427 LoweredMI = MCInstBuilder(SystemZ::VLVGP) 428 .addReg(MI->getOperand(0).getReg()) 429 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg())) 430 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())); 431 break; 432 433 case SystemZ::VLR32: 434 case SystemZ::VLR64: 435 LoweredMI = MCInstBuilder(SystemZ::VLR) 436 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 437 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())); 438 break; 439 440 case SystemZ::VL: 441 Lower.lower(MI, LoweredMI); 442 lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign); 443 break; 444 445 case SystemZ::VST: 446 Lower.lower(MI, LoweredMI); 447 lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign); 448 break; 449 450 case SystemZ::VLM: 451 Lower.lower(MI, LoweredMI); 452 lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign); 453 break; 454 455 case SystemZ::VSTM: 456 Lower.lower(MI, LoweredMI); 457 lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign); 458 break; 459 460 case SystemZ::VL32: 461 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF); 462 break; 463 464 case SystemZ::VL64: 465 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG); 466 break; 467 468 case SystemZ::VST32: 469 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF); 470 break; 471 472 case SystemZ::VST64: 473 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG); 474 break; 475 476 case SystemZ::LFER: 477 LoweredMI = MCInstBuilder(SystemZ::VLGVF) 478 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg())) 479 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())) 480 .addReg(0).addImm(0); 481 break; 482 483 case SystemZ::LEFR: 484 LoweredMI = MCInstBuilder(SystemZ::VLVGF) 485 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 486 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 487 .addReg(MI->getOperand(1).getReg()) 488 .addReg(0).addImm(0); 489 break; 490 491 #define LOWER_LOW(NAME) \ 492 case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break 493 494 LOWER_LOW(IILL); 495 LOWER_LOW(IILH); 496 LOWER_LOW(TMLL); 497 LOWER_LOW(TMLH); 498 LOWER_LOW(NILL); 499 LOWER_LOW(NILH); 500 LOWER_LOW(NILF); 501 LOWER_LOW(OILL); 502 LOWER_LOW(OILH); 503 LOWER_LOW(OILF); 504 LOWER_LOW(XILF); 505 506 #undef LOWER_LOW 507 508 #define LOWER_HIGH(NAME) \ 509 case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break 510 511 LOWER_HIGH(IIHL); 512 LOWER_HIGH(IIHH); 513 LOWER_HIGH(TMHL); 514 LOWER_HIGH(TMHH); 515 LOWER_HIGH(NIHL); 516 LOWER_HIGH(NIHH); 517 LOWER_HIGH(NIHF); 518 LOWER_HIGH(OIHL); 519 LOWER_HIGH(OIHH); 520 LOWER_HIGH(OIHF); 521 LOWER_HIGH(XIHF); 522 523 #undef LOWER_HIGH 524 525 case SystemZ::Serialize: 526 if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization()) 527 LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 528 .addImm(14).addReg(SystemZ::R0D); 529 else 530 LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 531 .addImm(15).addReg(SystemZ::R0D); 532 break; 533 534 // We want to emit "j .+2" for traps, jumping to the relative immediate field 535 // of the jump instruction, which is an illegal instruction. We cannot emit a 536 // "." symbol, so create and emit a temp label before the instruction and use 537 // that instead. 538 case SystemZ::Trap: { 539 MCSymbol *DotSym = OutContext.createTempSymbol(); 540 OutStreamer->emitLabel(DotSym); 541 542 const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 543 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 544 LoweredMI = MCInstBuilder(SystemZ::J) 545 .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 546 } 547 break; 548 549 // Conditional traps will create a branch on condition instruction that jumps 550 // to the relative immediate field of the jump instruction. (eg. "jo .+2") 551 case SystemZ::CondTrap: { 552 MCSymbol *DotSym = OutContext.createTempSymbol(); 553 OutStreamer->emitLabel(DotSym); 554 555 const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 556 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 557 LoweredMI = MCInstBuilder(SystemZ::BRC) 558 .addImm(MI->getOperand(0).getImm()) 559 .addImm(MI->getOperand(1).getImm()) 560 .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 561 } 562 break; 563 564 case TargetOpcode::FENTRY_CALL: 565 LowerFENTRY_CALL(*MI, Lower); 566 return; 567 568 case TargetOpcode::STACKMAP: 569 LowerSTACKMAP(*MI); 570 return; 571 572 case TargetOpcode::PATCHPOINT: 573 LowerPATCHPOINT(*MI, Lower); 574 return; 575 576 case SystemZ::EXRL_Pseudo: { 577 unsigned TargetInsOpc = MI->getOperand(0).getImm(); 578 Register LenMinus1Reg = MI->getOperand(1).getReg(); 579 Register DestReg = MI->getOperand(2).getReg(); 580 int64_t DestDisp = MI->getOperand(3).getImm(); 581 Register SrcReg = MI->getOperand(4).getReg(); 582 int64_t SrcDisp = MI->getOperand(5).getImm(); 583 584 SystemZTargetStreamer *TS = getTargetStreamer(); 585 MCSymbol *DotSym = nullptr; 586 MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg) 587 .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp); 588 SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget()); 589 SystemZTargetStreamer::EXRLT2SymMap::iterator I = 590 TS->EXRLTargets2Sym.find(ET_STI); 591 if (I != TS->EXRLTargets2Sym.end()) 592 DotSym = I->second; 593 else 594 TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol(); 595 const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 596 EmitToStreamer( 597 *OutStreamer, 598 MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot)); 599 return; 600 } 601 602 default: 603 Lower.lower(MI, LoweredMI); 604 break; 605 } 606 EmitToStreamer(*OutStreamer, LoweredMI); 607 } 608 609 // Emit the largest nop instruction smaller than or equal to NumBytes 610 // bytes. Return the size of nop emitted. 611 static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, 612 unsigned NumBytes, const MCSubtargetInfo &STI) { 613 if (NumBytes < 2) { 614 llvm_unreachable("Zero nops?"); 615 return 0; 616 } 617 else if (NumBytes < 4) { 618 OutStreamer.emitInstruction( 619 MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI); 620 return 2; 621 } 622 else if (NumBytes < 6) { 623 OutStreamer.emitInstruction( 624 MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0), 625 STI); 626 return 4; 627 } 628 else { 629 MCSymbol *DotSym = OutContext.createTempSymbol(); 630 const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 631 OutStreamer.emitLabel(DotSym); 632 OutStreamer.emitInstruction( 633 MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI); 634 return 6; 635 } 636 } 637 638 void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI, 639 SystemZMCInstLower &Lower) { 640 MCContext &Ctx = MF->getContext(); 641 if (MF->getFunction().hasFnAttribute("mrecord-mcount")) { 642 MCSymbol *DotSym = OutContext.createTempSymbol(); 643 OutStreamer->pushSection(); 644 OutStreamer->switchSection( 645 Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC)); 646 OutStreamer->emitSymbolValue(DotSym, 8); 647 OutStreamer->popSection(); 648 OutStreamer->emitLabel(DotSym); 649 } 650 651 if (MF->getFunction().hasFnAttribute("mnop-mcount")) { 652 EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo()); 653 return; 654 } 655 656 MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__"); 657 const MCSymbolRefExpr *Op = 658 MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx); 659 OutStreamer->emitInstruction( 660 MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op), 661 getSubtargetInfo()); 662 } 663 664 void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) { 665 auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo(); 666 667 unsigned NumNOPBytes = MI.getOperand(1).getImm(); 668 669 auto &Ctx = OutStreamer->getContext(); 670 MCSymbol *MILabel = Ctx.createTempSymbol(); 671 OutStreamer->emitLabel(MILabel); 672 673 SM.recordStackMap(*MILabel, MI); 674 assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!"); 675 676 // Scan ahead to trim the shadow. 677 unsigned ShadowBytes = 0; 678 const MachineBasicBlock &MBB = *MI.getParent(); 679 MachineBasicBlock::const_iterator MII(MI); 680 ++MII; 681 while (ShadowBytes < NumNOPBytes) { 682 if (MII == MBB.end() || 683 MII->getOpcode() == TargetOpcode::PATCHPOINT || 684 MII->getOpcode() == TargetOpcode::STACKMAP) 685 break; 686 ShadowBytes += TII->getInstSizeInBytes(*MII); 687 if (MII->isCall()) 688 break; 689 ++MII; 690 } 691 692 // Emit nops. 693 while (ShadowBytes < NumNOPBytes) 694 ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes, 695 getSubtargetInfo()); 696 } 697 698 // Lower a patchpoint of the form: 699 // [<def>], <id>, <numBytes>, <target>, <numArgs> 700 void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI, 701 SystemZMCInstLower &Lower) { 702 auto &Ctx = OutStreamer->getContext(); 703 MCSymbol *MILabel = Ctx.createTempSymbol(); 704 OutStreamer->emitLabel(MILabel); 705 706 SM.recordPatchPoint(*MILabel, MI); 707 PatchPointOpers Opers(&MI); 708 709 unsigned EncodedBytes = 0; 710 const MachineOperand &CalleeMO = Opers.getCallTarget(); 711 712 if (CalleeMO.isImm()) { 713 uint64_t CallTarget = CalleeMO.getImm(); 714 if (CallTarget) { 715 unsigned ScratchIdx = -1; 716 unsigned ScratchReg = 0; 717 do { 718 ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1); 719 ScratchReg = MI.getOperand(ScratchIdx).getReg(); 720 } while (ScratchReg == SystemZ::R0D); 721 722 // Materialize the call target address 723 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF) 724 .addReg(ScratchReg) 725 .addImm(CallTarget & 0xFFFFFFFF)); 726 EncodedBytes += 6; 727 if (CallTarget >> 32) { 728 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF) 729 .addReg(ScratchReg) 730 .addImm(CallTarget >> 32)); 731 EncodedBytes += 6; 732 } 733 734 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 735 .addReg(SystemZ::R14D) 736 .addReg(ScratchReg)); 737 EncodedBytes += 2; 738 } 739 } else if (CalleeMO.isGlobal()) { 740 const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT); 741 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL) 742 .addReg(SystemZ::R14D) 743 .addExpr(Expr)); 744 EncodedBytes += 6; 745 } 746 747 // Emit padding. 748 unsigned NumBytes = Opers.getNumPatchBytes(); 749 assert(NumBytes >= EncodedBytes && 750 "Patchpoint can't request size less than the length of a call."); 751 assert((NumBytes - EncodedBytes) % 2 == 0 && 752 "Invalid number of NOP bytes requested!"); 753 while (EncodedBytes < NumBytes) 754 EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes, 755 getSubtargetInfo()); 756 } 757 758 // The *alignment* of 128-bit vector types is different between the software 759 // and hardware vector ABIs. If the there is an externally visible use of a 760 // vector type in the module it should be annotated with an attribute. 761 void SystemZAsmPrinter::emitAttributes(Module &M) { 762 if (M.getModuleFlag("s390x-visible-vector-ABI")) { 763 bool HasVectorFeature = 764 TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureVector); 765 OutStreamer->emitGNUAttribute(8, HasVectorFeature ? 2 : 1); 766 } 767 } 768 769 // Convert a SystemZ-specific constant pool modifier into the associated 770 // MCSymbolRefExpr variant kind. 771 static MCSymbolRefExpr::VariantKind 772 getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { 773 switch (Modifier) { 774 case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD; 775 case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM; 776 case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF; 777 case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF; 778 } 779 llvm_unreachable("Invalid SystemCPModifier!"); 780 } 781 782 void SystemZAsmPrinter::emitMachineConstantPoolValue( 783 MachineConstantPoolValue *MCPV) { 784 auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV); 785 786 const MCExpr *Expr = 787 MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()), 788 getModifierVariantKind(ZCPV->getModifier()), 789 OutContext); 790 uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType()); 791 792 OutStreamer->emitValue(Expr, Size); 793 } 794 795 static void printFormattedRegName(const MCAsmInfo *MAI, unsigned RegNo, 796 raw_ostream &OS) { 797 const char *RegName = SystemZInstPrinter::getRegisterName(RegNo); 798 if (MAI->getAssemblerDialect() == AD_HLASM) { 799 // Skip register prefix so that only register number is left 800 assert(isalpha(RegName[0]) && isdigit(RegName[1])); 801 OS << (RegName + 1); 802 } else 803 OS << '%' << RegName; 804 } 805 806 static void printOperand(const MCOperand &MCOp, const MCAsmInfo *MAI, 807 raw_ostream &OS) { 808 if (MCOp.isReg()) { 809 if (!MCOp.getReg()) 810 OS << '0'; 811 else 812 printFormattedRegName(MAI, MCOp.getReg(), OS); 813 } else if (MCOp.isImm()) 814 OS << MCOp.getImm(); 815 else if (MCOp.isExpr()) 816 MCOp.getExpr()->print(OS, MAI); 817 else 818 llvm_unreachable("Invalid operand"); 819 } 820 821 static void printAddress(const MCAsmInfo *MAI, unsigned Base, 822 const MCOperand &DispMO, unsigned Index, 823 raw_ostream &OS) { 824 printOperand(DispMO, MAI, OS); 825 if (Base || Index) { 826 OS << '('; 827 if (Index) { 828 printFormattedRegName(MAI, Index, OS); 829 if (Base) 830 OS << ','; 831 } 832 if (Base) 833 printFormattedRegName(MAI, Base, OS); 834 OS << ')'; 835 } 836 } 837 838 bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 839 const char *ExtraCode, 840 raw_ostream &OS) { 841 const MCRegisterInfo &MRI = *TM.getMCRegisterInfo(); 842 const MachineOperand &MO = MI->getOperand(OpNo); 843 MCOperand MCOp; 844 if (ExtraCode) { 845 if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() && 846 SystemZ::GR128BitRegClass.contains(MO.getReg())) 847 MCOp = 848 MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64)); 849 else 850 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS); 851 } else { 852 SystemZMCInstLower Lower(MF->getContext(), *this); 853 MCOp = Lower.lowerOperand(MO); 854 } 855 printOperand(MCOp, MAI, OS); 856 return false; 857 } 858 859 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 860 unsigned OpNo, 861 const char *ExtraCode, 862 raw_ostream &OS) { 863 printAddress(MAI, MI->getOperand(OpNo).getReg(), 864 MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()), 865 MI->getOperand(OpNo + 2).getReg(), OS); 866 return false; 867 } 868 869 void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) { 870 emitAttributes(M); 871 } 872 873 void SystemZAsmPrinter::emitFunctionBodyEnd() { 874 if (TM.getTargetTriple().isOSzOS()) { 875 // Emit symbol for the end of function if the z/OS target streamer 876 // is used. This is needed to calculate the size of the function. 877 MCSymbol *FnEndSym = createTempSymbol("func_end"); 878 OutStreamer->emitLabel(FnEndSym); 879 880 OutStreamer->pushSection(); 881 OutStreamer->switchSection(getObjFileLowering().getPPA1Section()); 882 emitPPA1(FnEndSym); 883 OutStreamer->popSection(); 884 885 CurrentFnPPA1Sym = nullptr; 886 CurrentFnEPMarkerSym = nullptr; 887 } 888 } 889 890 static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg, 891 bool StackProtector, bool FPRMask, bool VRMask) { 892 enum class PPA1Flag1 : uint8_t { 893 DSA64Bit = (0x80 >> 0), 894 VarArg = (0x80 >> 7), 895 LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit) 896 }; 897 enum class PPA1Flag2 : uint8_t { 898 ExternalProcedure = (0x80 >> 0), 899 STACKPROTECTOR = (0x80 >> 3), 900 LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure) 901 }; 902 enum class PPA1Flag3 : uint8_t { 903 FPRMask = (0x80 >> 2), 904 LLVM_MARK_AS_BITMASK_ENUM(FPRMask) 905 }; 906 enum class PPA1Flag4 : uint8_t { 907 EPMOffsetPresent = (0x80 >> 0), 908 VRMask = (0x80 >> 2), 909 ProcedureNamePresent = (0x80 >> 7), 910 LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent) 911 }; 912 913 // Declare optional section flags that can be modified. 914 auto Flags1 = PPA1Flag1(0); 915 auto Flags2 = PPA1Flag2::ExternalProcedure; 916 auto Flags3 = PPA1Flag3(0); 917 auto Flags4 = PPA1Flag4::EPMOffsetPresent | PPA1Flag4::ProcedureNamePresent; 918 919 Flags1 |= PPA1Flag1::DSA64Bit; 920 921 if (VarArg) 922 Flags1 |= PPA1Flag1::VarArg; 923 924 if (StackProtector) 925 Flags2 |= PPA1Flag2::STACKPROTECTOR; 926 927 // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in. 928 if (FPRMask) 929 Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag. 930 931 if (VRMask) 932 Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag. 933 934 OutStreamer->AddComment("PPA1 Flags 1"); 935 if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit) 936 OutStreamer->AddComment(" Bit 0: 1 = 64-bit DSA"); 937 else 938 OutStreamer->AddComment(" Bit 0: 0 = 32-bit DSA"); 939 if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg) 940 OutStreamer->AddComment(" Bit 7: 1 = Vararg function"); 941 OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1. 942 943 OutStreamer->AddComment("PPA1 Flags 2"); 944 if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure) 945 OutStreamer->AddComment(" Bit 0: 1 = External procedure"); 946 if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR) 947 OutStreamer->AddComment(" Bit 3: 1 = STACKPROTECT is enabled"); 948 else 949 OutStreamer->AddComment(" Bit 3: 0 = STACKPROTECT is not enabled"); 950 OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2. 951 952 OutStreamer->AddComment("PPA1 Flags 3"); 953 if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask) 954 OutStreamer->AddComment(" Bit 2: 1 = FP Reg Mask is in optional area"); 955 OutStreamer->emitInt8( 956 static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections). 957 958 OutStreamer->AddComment("PPA1 Flags 4"); 959 if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask) 960 OutStreamer->AddComment(" Bit 2: 1 = Vector Reg Mask is in optional area"); 961 OutStreamer->emitInt8(static_cast<uint8_t>( 962 Flags4)); // Flags 4 (optional sections, always emit these). 963 } 964 965 void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) { 966 const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo(); 967 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 968 const auto TargetHasVector = Subtarget.hasVector(); 969 970 const SystemZMachineFunctionInfo *ZFI = 971 MF->getInfo<SystemZMachineFunctionInfo>(); 972 const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>( 973 Subtarget.getFrameLowering()); 974 const MachineFrameInfo &MFFrame = MF->getFrameInfo(); 975 976 // Get saved GPR/FPR/VPR masks. 977 const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo(); 978 uint16_t SavedGPRMask = 0; 979 uint16_t SavedFPRMask = 0; 980 uint8_t SavedVRMask = 0; 981 int64_t OffsetFPR = 0; 982 int64_t OffsetVR = 0; 983 const int64_t TopOfStack = 984 MFFrame.getOffsetAdjustment() + MFFrame.getStackSize(); 985 986 // Loop over the spilled registers. The CalleeSavedInfo can't be used because 987 // it does not contain all spilled registers. 988 for (unsigned I = ZFI->getSpillGPRRegs().LowGPR, 989 E = ZFI->getSpillGPRRegs().HighGPR; 990 I && E && I <= E; ++I) { 991 unsigned V = TRI->getEncodingValue((Register)I); 992 assert(V < 16 && "GPR index out of range"); 993 SavedGPRMask |= 1 << (15 - V); 994 } 995 996 for (auto &CS : CSI) { 997 unsigned Reg = CS.getReg(); 998 unsigned I = TRI->getEncodingValue(Reg); 999 1000 if (SystemZ::FP64BitRegClass.contains(Reg)) { 1001 assert(I < 16 && "FPR index out of range"); 1002 SavedFPRMask |= 1 << (15 - I); 1003 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx()); 1004 if (Temp < OffsetFPR) 1005 OffsetFPR = Temp; 1006 } else if (SystemZ::VR128BitRegClass.contains(Reg)) { 1007 assert(I >= 16 && I <= 23 && "VPR index out of range"); 1008 unsigned BitNum = I - 16; 1009 SavedVRMask |= 1 << (7 - BitNum); 1010 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx()); 1011 if (Temp < OffsetVR) 1012 OffsetVR = Temp; 1013 } 1014 } 1015 1016 // Adjust the offset. 1017 OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0; 1018 OffsetVR += (OffsetVR < 0) ? TopOfStack : 0; 1019 1020 // Get alloca register. 1021 uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF)); 1022 uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0; 1023 assert(AllocaReg < 16 && "Can't have alloca register larger than 15"); 1024 (void)AllocaReg; 1025 1026 // Build FPR save area offset. 1027 uint32_t FrameAndFPROffset = 0; 1028 if (SavedFPRMask) { 1029 uint64_t FPRSaveAreaOffset = OffsetFPR; 1030 assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range"); 1031 1032 FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits. 1033 FrameAndFPROffset |= FrameReg << 28; // Put into top 4 bits. 1034 } 1035 1036 // Build VR save area offset. 1037 uint32_t FrameAndVROffset = 0; 1038 if (TargetHasVector && SavedVRMask) { 1039 uint64_t VRSaveAreaOffset = OffsetVR; 1040 assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range"); 1041 1042 FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits. 1043 FrameAndVROffset |= FrameReg << 28; // Put into top 4 bits. 1044 } 1045 1046 // Emit PPA1 section. 1047 OutStreamer->AddComment("PPA1"); 1048 OutStreamer->emitLabel(CurrentFnPPA1Sym); 1049 OutStreamer->AddComment("Version"); 1050 OutStreamer->emitInt8(0x02); // Version. 1051 OutStreamer->AddComment("LE Signature X'CE'"); 1052 OutStreamer->emitInt8(0xCE); // CEL signature. 1053 OutStreamer->AddComment("Saved GPR Mask"); 1054 OutStreamer->emitInt16(SavedGPRMask); 1055 1056 emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(), 1057 MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0, 1058 TargetHasVector && SavedVRMask != 0); 1059 1060 OutStreamer->AddComment("Length/4 of Parms"); 1061 OutStreamer->emitInt16( 1062 static_cast<uint16_t>(ZFI->getSizeOfFnParams() / 4)); // Parms/4. 1063 OutStreamer->AddComment("Length of Code"); 1064 OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4); 1065 1066 // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3). 1067 if (SavedFPRMask) { 1068 OutStreamer->AddComment("FPR mask"); 1069 OutStreamer->emitInt16(SavedFPRMask); 1070 OutStreamer->AddComment("AR mask"); 1071 OutStreamer->emitInt16(0); // AR Mask, unused currently. 1072 OutStreamer->AddComment("FPR Save Area Locator"); 1073 OutStreamer->AddComment(Twine(" Bit 0-3: Register R") 1074 .concat(utostr(FrameAndFPROffset >> 28)) 1075 .str()); 1076 OutStreamer->AddComment(Twine(" Bit 4-31: Offset ") 1077 .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF)) 1078 .str()); 1079 OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with 1080 // register to add value to 1081 // (alloca reg). 1082 } 1083 1084 // Emit saved VR mask to VR save area. 1085 if (TargetHasVector && SavedVRMask) { 1086 OutStreamer->AddComment("VR mask"); 1087 OutStreamer->emitInt8(SavedVRMask); 1088 OutStreamer->emitInt8(0); // Reserved. 1089 OutStreamer->emitInt16(0); // Also reserved. 1090 OutStreamer->AddComment("VR Save Area Locator"); 1091 OutStreamer->AddComment(Twine(" Bit 0-3: Register R") 1092 .concat(utostr(FrameAndVROffset >> 28)) 1093 .str()); 1094 OutStreamer->AddComment(Twine(" Bit 4-31: Offset ") 1095 .concat(utostr(FrameAndVROffset & 0x0FFFFFFF)) 1096 .str()); 1097 OutStreamer->emitInt32(FrameAndVROffset); 1098 } 1099 1100 // Emit offset to entry point optional section (0x80 of flags 4). 1101 OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym, 1102 4); 1103 } 1104 1105 void SystemZAsmPrinter::emitFunctionEntryLabel() { 1106 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 1107 1108 if (Subtarget.getTargetTriple().isOSzOS()) { 1109 MCContext &OutContext = OutStreamer->getContext(); 1110 1111 // Save information for later use. 1112 std::string N(MF->getFunction().hasName() 1113 ? Twine(MF->getFunction().getName()).concat("_").str() 1114 : ""); 1115 1116 CurrentFnEPMarkerSym = 1117 OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true); 1118 CurrentFnPPA1Sym = 1119 OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true); 1120 1121 // EntryPoint Marker 1122 const MachineFrameInfo &MFFrame = MF->getFrameInfo(); 1123 bool IsUsingAlloca = MFFrame.hasVarSizedObjects(); 1124 1125 // Set Flags 1126 uint8_t Flags = 0; 1127 if (IsUsingAlloca) 1128 Flags |= 0x04; 1129 1130 uint32_t DSASize = MFFrame.getStackSize(); 1131 1132 // Combine into top 27 bits of DSASize and bottom 5 bits of Flags. 1133 uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5 1134 DSAAndFlags |= Flags; 1135 1136 // Emit entry point marker section. 1137 OutStreamer->AddComment("XPLINK Routine Layout Entry"); 1138 OutStreamer->emitLabel(CurrentFnEPMarkerSym); 1139 OutStreamer->AddComment("Eyecatcher 0x00C300C500C500"); 1140 OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher. 1141 OutStreamer->AddComment("Mark Type C'1'"); 1142 OutStreamer->emitInt8(0xF1); // Mark Type. 1143 OutStreamer->AddComment("Offset to PPA1"); 1144 OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym, 1145 4); 1146 if (OutStreamer->isVerboseAsm()) { 1147 OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize)); 1148 OutStreamer->AddComment("Entry Flags"); 1149 if (Flags & 0x04) 1150 OutStreamer->AddComment(" Bit 2: 1 = Uses alloca"); 1151 else 1152 OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca"); 1153 } 1154 OutStreamer->emitInt32(DSAAndFlags); 1155 } 1156 1157 AsmPrinter::emitFunctionEntryLabel(); 1158 } 1159 1160 // Force static initialization. 1161 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() { 1162 RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget()); 1163 } 1164