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