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