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