1778 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8//9// Streams SystemZ assembly language and associated data, in the form of10// MCInsts and MCExprs respectively.11//12//===----------------------------------------------------------------------===//13 14#include "SystemZAsmPrinter.h"15#include "MCTargetDesc/SystemZGNUInstPrinter.h"16#include "MCTargetDesc/SystemZHLASMInstPrinter.h"17#include "MCTargetDesc/SystemZMCAsmInfo.h"18#include "MCTargetDesc/SystemZMCTargetDesc.h"19#include "SystemZConstantPoolValue.h"20#include "SystemZMCInstLower.h"21#include "TargetInfo/SystemZTargetInfo.h"22#include "llvm/ADT/StringExtras.h"23#include "llvm/BinaryFormat/ELF.h"24#include "llvm/BinaryFormat/GOFF.h"25#include "llvm/CodeGen/MachineModuleInfoImpls.h"26#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"27#include "llvm/IR/Mangler.h"28#include "llvm/IR/Module.h"29#include "llvm/MC/MCExpr.h"30#include "llvm/MC/MCInstBuilder.h"31#include "llvm/MC/MCSectionELF.h"32#include "llvm/MC/MCStreamer.h"33#include "llvm/MC/TargetRegistry.h"34#include "llvm/Support/Chrono.h"35#include "llvm/Support/Compiler.h"36#include "llvm/Support/ConvertEBCDIC.h"37#include "llvm/Support/FormatVariadic.h"38 39using namespace llvm;40 41// Return an RI instruction like MI with opcode Opcode, but with the42// GR64 register operands turned into GR32s.43static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {44 if (MI->isCompare())45 return MCInstBuilder(Opcode)46 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))47 .addImm(MI->getOperand(1).getImm());48 else49 return MCInstBuilder(Opcode)50 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))51 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))52 .addImm(MI->getOperand(2).getImm());53}54 55// Return an RI instruction like MI with opcode Opcode, but with the56// GR64 register operands turned into GRH32s.57static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {58 if (MI->isCompare())59 return MCInstBuilder(Opcode)60 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))61 .addImm(MI->getOperand(1).getImm());62 else63 return MCInstBuilder(Opcode)64 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))65 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg()))66 .addImm(MI->getOperand(2).getImm());67}68 69// Return an RI instruction like MI with opcode Opcode, but with the70// R2 register turned into a GR64.71static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {72 return MCInstBuilder(Opcode)73 .addReg(MI->getOperand(0).getReg())74 .addReg(MI->getOperand(1).getReg())75 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))76 .addImm(MI->getOperand(3).getImm())77 .addImm(MI->getOperand(4).getImm())78 .addImm(MI->getOperand(5).getImm());79}80 81static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {82 StringRef Name = "__tls_get_offset";83 return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),84 SystemZ::S_PLT, Context);85}86 87static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {88 StringRef Name = "_GLOBAL_OFFSET_TABLE_";89 return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),90 Context);91}92 93// MI is an instruction that accepts an optional alignment hint,94// and which was already lowered to LoweredMI. If the alignment95// of the original memory operand is known, update LoweredMI to96// an instruction with the corresponding hint set.97static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI,98 unsigned Opcode) {99 if (MI->memoperands_empty())100 return;101 102 Align Alignment = Align(16);103 for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(),104 EE = MI->memoperands_end(); MMOI != EE; ++MMOI)105 if ((*MMOI)->getAlign() < Alignment)106 Alignment = (*MMOI)->getAlign();107 108 unsigned AlignmentHint = 0;109 if (Alignment >= Align(16))110 AlignmentHint = 4;111 else if (Alignment >= Align(8))112 AlignmentHint = 3;113 if (AlignmentHint == 0)114 return;115 116 LoweredMI.setOpcode(Opcode);117 LoweredMI.addOperand(MCOperand::createImm(AlignmentHint));118}119 120// MI loads the high part of a vector from memory. Return an instruction121// that uses replicating vector load Opcode to do the same thing.122static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {123 return MCInstBuilder(Opcode)124 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))125 .addReg(MI->getOperand(1).getReg())126 .addImm(MI->getOperand(2).getImm())127 .addReg(MI->getOperand(3).getReg());128}129 130// MI stores the high part of a vector to memory. Return an instruction131// that uses elemental vector store Opcode to do the same thing.132static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {133 return MCInstBuilder(Opcode)134 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))135 .addReg(MI->getOperand(1).getReg())136 .addImm(MI->getOperand(2).getImm())137 .addReg(MI->getOperand(3).getReg())138 .addImm(0);139}140 141// MI extracts the first element of the source vector.142static MCInst lowerVecEltExtraction(const MachineInstr *MI, unsigned Opcode) {143 return MCInstBuilder(Opcode)144 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg()))145 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()))146 .addReg(0)147 .addImm(0);148}149 150// MI inserts value into the first element of the destination vector.151static MCInst lowerVecEltInsertion(const MachineInstr *MI, unsigned Opcode) {152 return MCInstBuilder(Opcode)153 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))154 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))155 .addReg(MI->getOperand(1).getReg())156 .addReg(0)157 .addImm(0);158}159 160// The XPLINK ABI requires that a no-op encoding the call type is emitted after161// each call to a subroutine. This information can be used by the called162// function to determine its entry point, e.g. for generating a backtrace. The163// call type is encoded as a register number in the bcr instruction. See164// enumeration CallType for the possible values.165void SystemZAsmPrinter::emitCallInformation(CallType CT) {166 EmitToStreamer(*OutStreamer,167 MCInstBuilder(SystemZ::BCRAsm)168 .addImm(0)169 .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));170}171 172uint32_t SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MCSymbol *Sym,173 unsigned SlotKind) {174 auto Key = std::make_pair(Sym, SlotKind);175 auto It = Displacements.find(Key);176 177 if (It != Displacements.end())178 return (*It).second;179 180 // Determine length of descriptor.181 uint32_t Length;182 switch (SlotKind) {183 case SystemZII::MO_ADA_DIRECT_FUNC_DESC:184 Length = 2 * PointerSize;185 break;186 default:187 Length = PointerSize;188 break;189 }190 191 uint32_t Displacement = NextDisplacement;192 Displacements[std::make_pair(Sym, SlotKind)] = NextDisplacement;193 NextDisplacement += Length;194 195 return Displacement;196}197 198uint32_t199SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MachineOperand MO) {200 MCSymbol *Sym;201 if (MO.getType() == MachineOperand::MO_GlobalAddress) {202 const GlobalValue *GV = MO.getGlobal();203 Sym = MO.getParent()->getMF()->getTarget().getSymbol(GV);204 assert(Sym && "No symbol");205 } else if (MO.getType() == MachineOperand::MO_ExternalSymbol) {206 const char *SymName = MO.getSymbolName();207 Sym = MO.getParent()->getMF()->getContext().getOrCreateSymbol(SymName);208 assert(Sym && "No symbol");209 } else210 llvm_unreachable("Unexpected operand type");211 212 unsigned ADAslotType = MO.getTargetFlags();213 return insert(Sym, ADAslotType);214}215 216void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {217 SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(),218 getSubtargetInfo().getFeatureBits());219 220 SystemZMCInstLower Lower(MF->getContext(), *this);221 MCInst LoweredMI;222 switch (MI->getOpcode()) {223 case SystemZ::Return:224 LoweredMI = MCInstBuilder(SystemZ::BR)225 .addReg(SystemZ::R14D);226 break;227 228 case SystemZ::Return_XPLINK:229 LoweredMI = MCInstBuilder(SystemZ::B)230 .addReg(SystemZ::R7D)231 .addImm(2)232 .addReg(0);233 break;234 235 case SystemZ::CondReturn:236 LoweredMI = MCInstBuilder(SystemZ::BCR)237 .addImm(MI->getOperand(0).getImm())238 .addImm(MI->getOperand(1).getImm())239 .addReg(SystemZ::R14D);240 break;241 242 case SystemZ::CondReturn_XPLINK:243 LoweredMI = MCInstBuilder(SystemZ::BC)244 .addImm(MI->getOperand(0).getImm())245 .addImm(MI->getOperand(1).getImm())246 .addReg(SystemZ::R7D)247 .addImm(2)248 .addReg(0);249 break;250 251 case SystemZ::CRBReturn:252 LoweredMI = MCInstBuilder(SystemZ::CRB)253 .addReg(MI->getOperand(0).getReg())254 .addReg(MI->getOperand(1).getReg())255 .addImm(MI->getOperand(2).getImm())256 .addReg(SystemZ::R14D)257 .addImm(0);258 break;259 260 case SystemZ::CGRBReturn:261 LoweredMI = MCInstBuilder(SystemZ::CGRB)262 .addReg(MI->getOperand(0).getReg())263 .addReg(MI->getOperand(1).getReg())264 .addImm(MI->getOperand(2).getImm())265 .addReg(SystemZ::R14D)266 .addImm(0);267 break;268 269 case SystemZ::CIBReturn:270 LoweredMI = MCInstBuilder(SystemZ::CIB)271 .addReg(MI->getOperand(0).getReg())272 .addImm(MI->getOperand(1).getImm())273 .addImm(MI->getOperand(2).getImm())274 .addReg(SystemZ::R14D)275 .addImm(0);276 break;277 278 case SystemZ::CGIBReturn:279 LoweredMI = MCInstBuilder(SystemZ::CGIB)280 .addReg(MI->getOperand(0).getReg())281 .addImm(MI->getOperand(1).getImm())282 .addImm(MI->getOperand(2).getImm())283 .addReg(SystemZ::R14D)284 .addImm(0);285 break;286 287 case SystemZ::CLRBReturn:288 LoweredMI = MCInstBuilder(SystemZ::CLRB)289 .addReg(MI->getOperand(0).getReg())290 .addReg(MI->getOperand(1).getReg())291 .addImm(MI->getOperand(2).getImm())292 .addReg(SystemZ::R14D)293 .addImm(0);294 break;295 296 case SystemZ::CLGRBReturn:297 LoweredMI = MCInstBuilder(SystemZ::CLGRB)298 .addReg(MI->getOperand(0).getReg())299 .addReg(MI->getOperand(1).getReg())300 .addImm(MI->getOperand(2).getImm())301 .addReg(SystemZ::R14D)302 .addImm(0);303 break;304 305 case SystemZ::CLIBReturn:306 LoweredMI = MCInstBuilder(SystemZ::CLIB)307 .addReg(MI->getOperand(0).getReg())308 .addImm(MI->getOperand(1).getImm())309 .addImm(MI->getOperand(2).getImm())310 .addReg(SystemZ::R14D)311 .addImm(0);312 break;313 314 case SystemZ::CLGIBReturn:315 LoweredMI = MCInstBuilder(SystemZ::CLGIB)316 .addReg(MI->getOperand(0).getReg())317 .addImm(MI->getOperand(1).getImm())318 .addImm(MI->getOperand(2).getImm())319 .addReg(SystemZ::R14D)320 .addImm(0);321 break;322 323 case SystemZ::CallBRASL_XPLINK64:324 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)325 .addReg(SystemZ::R7D)326 .addExpr(Lower.getExpr(MI->getOperand(0),327 SystemZ::S_PLT)));328 emitCallInformation(CallType::BRASL7);329 return;330 331 case SystemZ::CallBASR_XPLINK64:332 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)333 .addReg(SystemZ::R7D)334 .addReg(MI->getOperand(0).getReg()));335 emitCallInformation(CallType::BASR76);336 return;337 338 case SystemZ::CallBASR_STACKEXT:339 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)340 .addReg(SystemZ::R3D)341 .addReg(MI->getOperand(0).getReg()));342 emitCallInformation(CallType::BASR33);343 return;344 345 case SystemZ::ADA_ENTRY_VALUE:346 case SystemZ::ADA_ENTRY: {347 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();348 const SystemZInstrInfo *TII = Subtarget.getInstrInfo();349 uint32_t Disp = ADATable.insert(MI->getOperand(1));350 Register TargetReg = MI->getOperand(0).getReg();351 352 Register ADAReg = MI->getOperand(2).getReg();353 Disp += MI->getOperand(3).getImm();354 bool LoadAddr = MI->getOpcode() == SystemZ::ADA_ENTRY;355 356 unsigned Op0 = LoadAddr ? SystemZ::LA : SystemZ::LG;357 unsigned Op = TII->getOpcodeForOffset(Op0, Disp);358 359 Register IndexReg = 0;360 if (!Op) {361 if (TargetReg != ADAReg) {362 IndexReg = TargetReg;363 // Use TargetReg to store displacement.364 EmitToStreamer(365 *OutStreamer,366 MCInstBuilder(SystemZ::LLILF).addReg(TargetReg).addImm(Disp));367 } else368 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::ALGFI)369 .addReg(TargetReg)370 .addReg(TargetReg)371 .addImm(Disp));372 Disp = 0;373 Op = Op0;374 }375 EmitToStreamer(*OutStreamer, MCInstBuilder(Op)376 .addReg(TargetReg)377 .addReg(ADAReg)378 .addImm(Disp)379 .addReg(IndexReg));380 381 return;382 }383 case SystemZ::CallBRASL:384 LoweredMI = MCInstBuilder(SystemZ::BRASL)385 .addReg(SystemZ::R14D)386 .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_PLT));387 break;388 389 case SystemZ::CallBASR:390 LoweredMI = MCInstBuilder(SystemZ::BASR)391 .addReg(SystemZ::R14D)392 .addReg(MI->getOperand(0).getReg());393 break;394 395 case SystemZ::CallJG:396 LoweredMI = MCInstBuilder(SystemZ::JG)397 .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_PLT));398 break;399 400 case SystemZ::CallBRCL:401 LoweredMI = MCInstBuilder(SystemZ::BRCL)402 .addImm(MI->getOperand(0).getImm())403 .addImm(MI->getOperand(1).getImm())404 .addExpr(Lower.getExpr(MI->getOperand(2), SystemZ::S_PLT));405 break;406 407 case SystemZ::CallBR:408 LoweredMI = MCInstBuilder(SystemZ::BR)409 .addReg(MI->getOperand(0).getReg());410 break;411 412 case SystemZ::CallBCR:413 LoweredMI = MCInstBuilder(SystemZ::BCR)414 .addImm(MI->getOperand(0).getImm())415 .addImm(MI->getOperand(1).getImm())416 .addReg(MI->getOperand(2).getReg());417 break;418 419 case SystemZ::CRBCall:420 LoweredMI = MCInstBuilder(SystemZ::CRB)421 .addReg(MI->getOperand(0).getReg())422 .addReg(MI->getOperand(1).getReg())423 .addImm(MI->getOperand(2).getImm())424 .addReg(MI->getOperand(3).getReg())425 .addImm(0);426 break;427 428 case SystemZ::CGRBCall:429 LoweredMI = MCInstBuilder(SystemZ::CGRB)430 .addReg(MI->getOperand(0).getReg())431 .addReg(MI->getOperand(1).getReg())432 .addImm(MI->getOperand(2).getImm())433 .addReg(MI->getOperand(3).getReg())434 .addImm(0);435 break;436 437 case SystemZ::CIBCall:438 LoweredMI = MCInstBuilder(SystemZ::CIB)439 .addReg(MI->getOperand(0).getReg())440 .addImm(MI->getOperand(1).getImm())441 .addImm(MI->getOperand(2).getImm())442 .addReg(MI->getOperand(3).getReg())443 .addImm(0);444 break;445 446 case SystemZ::CGIBCall:447 LoweredMI = MCInstBuilder(SystemZ::CGIB)448 .addReg(MI->getOperand(0).getReg())449 .addImm(MI->getOperand(1).getImm())450 .addImm(MI->getOperand(2).getImm())451 .addReg(MI->getOperand(3).getReg())452 .addImm(0);453 break;454 455 case SystemZ::CLRBCall:456 LoweredMI = MCInstBuilder(SystemZ::CLRB)457 .addReg(MI->getOperand(0).getReg())458 .addReg(MI->getOperand(1).getReg())459 .addImm(MI->getOperand(2).getImm())460 .addReg(MI->getOperand(3).getReg())461 .addImm(0);462 break;463 464 case SystemZ::CLGRBCall:465 LoweredMI = MCInstBuilder(SystemZ::CLGRB)466 .addReg(MI->getOperand(0).getReg())467 .addReg(MI->getOperand(1).getReg())468 .addImm(MI->getOperand(2).getImm())469 .addReg(MI->getOperand(3).getReg())470 .addImm(0);471 break;472 473 case SystemZ::CLIBCall:474 LoweredMI = MCInstBuilder(SystemZ::CLIB)475 .addReg(MI->getOperand(0).getReg())476 .addImm(MI->getOperand(1).getImm())477 .addImm(MI->getOperand(2).getImm())478 .addReg(MI->getOperand(3).getReg())479 .addImm(0);480 break;481 482 case SystemZ::CLGIBCall:483 LoweredMI = MCInstBuilder(SystemZ::CLGIB)484 .addReg(MI->getOperand(0).getReg())485 .addImm(MI->getOperand(1).getImm())486 .addImm(MI->getOperand(2).getImm())487 .addReg(MI->getOperand(3).getReg())488 .addImm(0);489 break;490 491 case SystemZ::TLS_GDCALL:492 LoweredMI =493 MCInstBuilder(SystemZ::BRASL)494 .addReg(SystemZ::R14D)495 .addExpr(getTLSGetOffset(MF->getContext()))496 .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_TLSGD));497 break;498 499 case SystemZ::TLS_LDCALL:500 LoweredMI =501 MCInstBuilder(SystemZ::BRASL)502 .addReg(SystemZ::R14D)503 .addExpr(getTLSGetOffset(MF->getContext()))504 .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_TLSLDM));505 break;506 507 case SystemZ::GOT:508 LoweredMI = MCInstBuilder(SystemZ::LARL)509 .addReg(MI->getOperand(0).getReg())510 .addExpr(getGlobalOffsetTable(MF->getContext()));511 break;512 513 case SystemZ::IILF64:514 LoweredMI = MCInstBuilder(SystemZ::IILF)515 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))516 .addImm(MI->getOperand(2).getImm());517 break;518 519 case SystemZ::IIHF64:520 LoweredMI = MCInstBuilder(SystemZ::IIHF)521 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))522 .addImm(MI->getOperand(2).getImm());523 break;524 525 case SystemZ::RISBHH:526 case SystemZ::RISBHL:527 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);528 break;529 530 case SystemZ::RISBLH:531 case SystemZ::RISBLL:532 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);533 break;534 535 case SystemZ::VLVGP32:536 LoweredMI = MCInstBuilder(SystemZ::VLVGP)537 .addReg(MI->getOperand(0).getReg())538 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg()))539 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()));540 break;541 542 case SystemZ::VLR32:543 case SystemZ::VLR64:544 LoweredMI = MCInstBuilder(SystemZ::VLR)545 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))546 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()));547 break;548 549 case SystemZ::VL:550 Lower.lower(MI, LoweredMI);551 lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign);552 break;553 554 case SystemZ::VST:555 Lower.lower(MI, LoweredMI);556 lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign);557 break;558 559 case SystemZ::VLM:560 Lower.lower(MI, LoweredMI);561 lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign);562 break;563 564 case SystemZ::VSTM:565 Lower.lower(MI, LoweredMI);566 lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign);567 break;568 569 case SystemZ::VL16:570 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPH);571 break;572 573 case SystemZ::VL32:574 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF);575 break;576 577 case SystemZ::VL64:578 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG);579 break;580 581 case SystemZ::VST16:582 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEH);583 break;584 585 case SystemZ::VST32:586 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF);587 break;588 589 case SystemZ::VST64:590 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG);591 break;592 593 case SystemZ::LFER:594 LoweredMI = lowerVecEltExtraction(MI, SystemZ::VLGVF);595 break;596 597 case SystemZ::LFER_16:598 LoweredMI = lowerVecEltExtraction(MI, SystemZ::VLGVH);599 break;600 601 case SystemZ::LEFR:602 LoweredMI = lowerVecEltInsertion(MI, SystemZ::VLVGF);603 break;604 605 case SystemZ::LEFR_16:606 LoweredMI = lowerVecEltInsertion(MI, SystemZ::VLVGH);607 break;608 609#define LOWER_LOW(NAME) \610 case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break611 612 LOWER_LOW(IILL);613 LOWER_LOW(IILH);614 LOWER_LOW(TMLL);615 LOWER_LOW(TMLH);616 LOWER_LOW(NILL);617 LOWER_LOW(NILH);618 LOWER_LOW(NILF);619 LOWER_LOW(OILL);620 LOWER_LOW(OILH);621 LOWER_LOW(OILF);622 LOWER_LOW(XILF);623 624#undef LOWER_LOW625 626#define LOWER_HIGH(NAME) \627 case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break628 629 LOWER_HIGH(IIHL);630 LOWER_HIGH(IIHH);631 LOWER_HIGH(TMHL);632 LOWER_HIGH(TMHH);633 LOWER_HIGH(NIHL);634 LOWER_HIGH(NIHH);635 LOWER_HIGH(NIHF);636 LOWER_HIGH(OIHL);637 LOWER_HIGH(OIHH);638 LOWER_HIGH(OIHF);639 LOWER_HIGH(XIHF);640 641#undef LOWER_HIGH642 643 case SystemZ::Serialize:644 if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())645 LoweredMI = MCInstBuilder(SystemZ::BCRAsm)646 .addImm(14).addReg(SystemZ::R0D);647 else648 LoweredMI = MCInstBuilder(SystemZ::BCRAsm)649 .addImm(15).addReg(SystemZ::R0D);650 break;651 652 // We want to emit "j .+2" for traps, jumping to the relative immediate field653 // of the jump instruction, which is an illegal instruction. We cannot emit a654 // "." symbol, so create and emit a temp label before the instruction and use655 // that instead.656 case SystemZ::Trap: {657 MCSymbol *DotSym = OutContext.createTempSymbol();658 OutStreamer->emitLabel(DotSym);659 660 const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);661 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);662 LoweredMI = MCInstBuilder(SystemZ::J)663 .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));664 }665 break;666 667 // Conditional traps will create a branch on condition instruction that jumps668 // to the relative immediate field of the jump instruction. (eg. "jo .+2")669 case SystemZ::CondTrap: {670 MCSymbol *DotSym = OutContext.createTempSymbol();671 OutStreamer->emitLabel(DotSym);672 673 const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);674 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);675 LoweredMI = MCInstBuilder(SystemZ::BRC)676 .addImm(MI->getOperand(0).getImm())677 .addImm(MI->getOperand(1).getImm())678 .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));679 }680 break;681 682 case TargetOpcode::FENTRY_CALL:683 LowerFENTRY_CALL(*MI, Lower);684 return;685 686 case TargetOpcode::STACKMAP:687 LowerSTACKMAP(*MI);688 return;689 690 case TargetOpcode::PATCHPOINT:691 LowerPATCHPOINT(*MI, Lower);692 return;693 694 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:695 LowerPATCHABLE_FUNCTION_ENTER(*MI, Lower);696 return;697 698 case TargetOpcode::PATCHABLE_RET:699 LowerPATCHABLE_RET(*MI, Lower);700 return;701 702 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:703 llvm_unreachable("PATCHABLE_FUNCTION_EXIT should never be emitted");704 705 case TargetOpcode::PATCHABLE_TAIL_CALL:706 // TODO: Define a trampoline `__xray_FunctionTailExit` and differentiate a707 // normal function exit from a tail exit.708 llvm_unreachable("Tail call is handled in the normal case. See comments "709 "around this assert.");710 711 case SystemZ::EXRL_Pseudo: {712 unsigned TargetInsOpc = MI->getOperand(0).getImm();713 Register LenMinus1Reg = MI->getOperand(1).getReg();714 Register DestReg = MI->getOperand(2).getReg();715 int64_t DestDisp = MI->getOperand(3).getImm();716 Register SrcReg = MI->getOperand(4).getReg();717 int64_t SrcDisp = MI->getOperand(5).getImm();718 719 SystemZTargetStreamer *TS = getTargetStreamer();720 MCInst ET = MCInstBuilder(TargetInsOpc)721 .addReg(DestReg)722 .addImm(DestDisp)723 .addImm(1)724 .addReg(SrcReg)725 .addImm(SrcDisp);726 SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());727 auto [It, Inserted] = TS->EXRLTargets2Sym.try_emplace(ET_STI);728 if (Inserted)729 It->second = OutContext.createTempSymbol();730 MCSymbol *DotSym = It->second;731 const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);732 EmitToStreamer(733 *OutStreamer,734 MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));735 return;736 }737 738 // EH_SjLj_Setup is a dummy terminator instruction of size 0.739 // It is used to handle the clobber register for builtin setjmp.740 case SystemZ::EH_SjLj_Setup:741 return;742 743 default:744 Lower.lower(MI, LoweredMI);745 break;746 }747 EmitToStreamer(*OutStreamer, LoweredMI);748}749 750// Emit the largest nop instruction smaller than or equal to NumBytes751// bytes. Return the size of nop emitted.752static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,753 unsigned NumBytes, const MCSubtargetInfo &STI) {754 if (NumBytes < 2) {755 llvm_unreachable("Zero nops?");756 return 0;757 }758 else if (NumBytes < 4) {759 OutStreamer.emitInstruction(760 MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);761 return 2;762 }763 else if (NumBytes < 6) {764 OutStreamer.emitInstruction(765 MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),766 STI);767 return 4;768 }769 else {770 MCSymbol *DotSym = OutContext.createTempSymbol();771 const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);772 OutStreamer.emitLabel(DotSym);773 OutStreamer.emitInstruction(774 MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);775 return 6;776 }777}778 779void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,780 SystemZMCInstLower &Lower) {781 MCContext &Ctx = MF->getContext();782 if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {783 MCSymbol *DotSym = OutContext.createTempSymbol();784 OutStreamer->pushSection();785 OutStreamer->switchSection(786 Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));787 OutStreamer->emitSymbolValue(DotSym, 8);788 OutStreamer->popSection();789 OutStreamer->emitLabel(DotSym);790 }791 792 if (MF->getFunction().hasFnAttribute("mnop-mcount")) {793 EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());794 return;795 }796 797 MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");798 const MCSymbolRefExpr *Op =799 MCSymbolRefExpr::create(fentry, SystemZ::S_PLT, Ctx);800 OutStreamer->emitInstruction(801 MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),802 getSubtargetInfo());803}804 805void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {806 auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo();807 808 unsigned NumNOPBytes = MI.getOperand(1).getImm();809 810 auto &Ctx = OutStreamer->getContext();811 MCSymbol *MILabel = Ctx.createTempSymbol();812 OutStreamer->emitLabel(MILabel);813 814 SM.recordStackMap(*MILabel, MI);815 assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");816 817 // Scan ahead to trim the shadow.818 unsigned ShadowBytes = 0;819 const MachineBasicBlock &MBB = *MI.getParent();820 MachineBasicBlock::const_iterator MII(MI);821 ++MII;822 while (ShadowBytes < NumNOPBytes) {823 if (MII == MBB.end() ||824 MII->getOpcode() == TargetOpcode::PATCHPOINT ||825 MII->getOpcode() == TargetOpcode::STACKMAP)826 break;827 ShadowBytes += TII->getInstSizeInBytes(*MII);828 if (MII->isCall())829 break;830 ++MII;831 }832 833 // Emit nops.834 while (ShadowBytes < NumNOPBytes)835 ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,836 getSubtargetInfo());837}838 839// Lower a patchpoint of the form:840// [<def>], <id>, <numBytes>, <target>, <numArgs>841void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,842 SystemZMCInstLower &Lower) {843 auto &Ctx = OutStreamer->getContext();844 MCSymbol *MILabel = Ctx.createTempSymbol();845 OutStreamer->emitLabel(MILabel);846 847 SM.recordPatchPoint(*MILabel, MI);848 PatchPointOpers Opers(&MI);849 850 unsigned EncodedBytes = 0;851 const MachineOperand &CalleeMO = Opers.getCallTarget();852 853 if (CalleeMO.isImm()) {854 uint64_t CallTarget = CalleeMO.getImm();855 if (CallTarget) {856 unsigned ScratchIdx = -1;857 unsigned ScratchReg = 0;858 do {859 ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);860 ScratchReg = MI.getOperand(ScratchIdx).getReg();861 } while (ScratchReg == SystemZ::R0D);862 863 // Materialize the call target address864 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)865 .addReg(ScratchReg)866 .addImm(CallTarget & 0xFFFFFFFF));867 EncodedBytes += 6;868 if (CallTarget >> 32) {869 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)870 .addReg(ScratchReg)871 .addImm(CallTarget >> 32));872 EncodedBytes += 6;873 }874 875 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)876 .addReg(SystemZ::R14D)877 .addReg(ScratchReg));878 EncodedBytes += 2;879 }880 } else if (CalleeMO.isGlobal()) {881 const MCExpr *Expr = Lower.getExpr(CalleeMO, SystemZ::S_PLT);882 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)883 .addReg(SystemZ::R14D)884 .addExpr(Expr));885 EncodedBytes += 6;886 }887 888 // Emit padding.889 unsigned NumBytes = Opers.getNumPatchBytes();890 assert(NumBytes >= EncodedBytes &&891 "Patchpoint can't request size less than the length of a call.");892 assert((NumBytes - EncodedBytes) % 2 == 0 &&893 "Invalid number of NOP bytes requested!");894 while (EncodedBytes < NumBytes)895 EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,896 getSubtargetInfo());897}898 899void SystemZAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(900 const MachineInstr &MI, SystemZMCInstLower &Lower) {901 // .begin:902 // j .end # -> stmg %r2, %r15, 16(%r15)903 // nop904 // llilf %2, FuncID905 // brasl %r14, __xray_FunctionEntry@GOT906 // .end:907 //908 // Update compiler-rt/lib/xray/xray_s390x.cpp accordingly when number909 // of instructions change.910 bool HasVectorFeature =911 TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureVector) &&912 !TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureSoftFloat);913 MCSymbol *FuncEntry = OutContext.getOrCreateSymbol(914 HasVectorFeature ? "__xray_FunctionEntryVec" : "__xray_FunctionEntry");915 MCSymbol *BeginOfSled = OutContext.createTempSymbol("xray_sled_", true);916 MCSymbol *EndOfSled = OutContext.createTempSymbol();917 OutStreamer->emitLabel(BeginOfSled);918 EmitToStreamer(*OutStreamer,919 MCInstBuilder(SystemZ::J)920 .addExpr(MCSymbolRefExpr::create(EndOfSled, OutContext)));921 EmitNop(OutContext, *OutStreamer, 2, getSubtargetInfo());922 EmitToStreamer(*OutStreamer,923 MCInstBuilder(SystemZ::LLILF).addReg(SystemZ::R2D).addImm(0));924 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)925 .addReg(SystemZ::R14D)926 .addExpr(MCSymbolRefExpr::create(927 FuncEntry, SystemZ::S_PLT, OutContext)));928 OutStreamer->emitLabel(EndOfSled);929 recordSled(BeginOfSled, MI, SledKind::FUNCTION_ENTER, 2);930}931 932void SystemZAsmPrinter::LowerPATCHABLE_RET(const MachineInstr &MI,933 SystemZMCInstLower &Lower) {934 unsigned OpCode = MI.getOperand(0).getImm();935 MCSymbol *FallthroughLabel = nullptr;936 if (OpCode == SystemZ::CondReturn) {937 FallthroughLabel = OutContext.createTempSymbol();938 int64_t Cond0 = MI.getOperand(1).getImm();939 int64_t Cond1 = MI.getOperand(2).getImm();940 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRC)941 .addImm(Cond0)942 .addImm(Cond1 ^ Cond0)943 .addExpr(MCSymbolRefExpr::create(944 FallthroughLabel, OutContext)));945 }946 // .begin:947 // br %r14 # -> stmg %r2, %r15, 24(%r15)948 // nop949 // nop950 // llilf %2,FuncID951 // j __xray_FunctionExit@GOT952 //953 // Update compiler-rt/lib/xray/xray_s390x.cpp accordingly when number954 // of instructions change.955 bool HasVectorFeature =956 TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureVector) &&957 !TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureSoftFloat);958 MCSymbol *FuncExit = OutContext.getOrCreateSymbol(959 HasVectorFeature ? "__xray_FunctionExitVec" : "__xray_FunctionExit");960 MCSymbol *BeginOfSled = OutContext.createTempSymbol("xray_sled_", true);961 OutStreamer->emitLabel(BeginOfSled);962 EmitToStreamer(*OutStreamer,963 MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D));964 EmitNop(OutContext, *OutStreamer, 4, getSubtargetInfo());965 EmitToStreamer(*OutStreamer,966 MCInstBuilder(SystemZ::LLILF).addReg(SystemZ::R2D).addImm(0));967 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::J)968 .addExpr(MCSymbolRefExpr::create(969 FuncExit, SystemZ::S_PLT, OutContext)));970 if (FallthroughLabel)971 OutStreamer->emitLabel(FallthroughLabel);972 recordSled(BeginOfSled, MI, SledKind::FUNCTION_EXIT, 2);973}974 975// The *alignment* of 128-bit vector types is different between the software976// and hardware vector ABIs. If the there is an externally visible use of a977// vector type in the module it should be annotated with an attribute.978void SystemZAsmPrinter::emitAttributes(Module &M) {979 if (M.getModuleFlag("s390x-visible-vector-ABI")) {980 bool HasVectorFeature =981 TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureVector);982 OutStreamer->emitGNUAttribute(8, HasVectorFeature ? 2 : 1);983 }984}985 986// Convert a SystemZ-specific constant pool modifier into the associated987// specifier.988static uint8_t getSpecifierFromModifier(SystemZCP::SystemZCPModifier Modifier) {989 switch (Modifier) {990 case SystemZCP::TLSGD:991 return SystemZ::S_TLSGD;992 case SystemZCP::TLSLDM:993 return SystemZ::S_TLSLDM;994 case SystemZCP::DTPOFF:995 return SystemZ::S_DTPOFF;996 case SystemZCP::NTPOFF:997 return SystemZ::S_NTPOFF;998 }999 llvm_unreachable("Invalid SystemCPModifier!");1000}1001 1002void SystemZAsmPrinter::emitMachineConstantPoolValue(1003 MachineConstantPoolValue *MCPV) {1004 auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);1005 1006 const MCExpr *Expr = MCSymbolRefExpr::create(1007 getSymbol(ZCPV->getGlobalValue()),1008 getSpecifierFromModifier(ZCPV->getModifier()), OutContext);1009 uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());1010 1011 OutStreamer->emitValue(Expr, Size);1012}1013 1014static void printFormattedRegName(const MCAsmInfo *MAI, unsigned RegNo,1015 raw_ostream &OS) {1016 const char *RegName;1017 if (MAI->getAssemblerDialect() == AD_HLASM) {1018 RegName = SystemZHLASMInstPrinter::getRegisterName(RegNo);1019 // Skip register prefix so that only register number is left1020 assert(isalpha(RegName[0]) && isdigit(RegName[1]));1021 OS << (RegName + 1);1022 } else {1023 RegName = SystemZGNUInstPrinter::getRegisterName(RegNo);1024 OS << '%' << RegName;1025 }1026}1027 1028static void printReg(unsigned Reg, const MCAsmInfo *MAI, raw_ostream &OS) {1029 if (!Reg)1030 OS << '0';1031 else1032 printFormattedRegName(MAI, Reg, OS);1033}1034 1035static void printOperand(const MCOperand &MCOp, const MCAsmInfo *MAI,1036 raw_ostream &OS) {1037 if (MCOp.isReg())1038 printReg(MCOp.getReg(), MAI, OS);1039 else if (MCOp.isImm())1040 OS << MCOp.getImm();1041 else if (MCOp.isExpr())1042 MAI->printExpr(OS, *MCOp.getExpr());1043 else1044 llvm_unreachable("Invalid operand");1045}1046 1047static void printAddress(const MCAsmInfo *MAI, unsigned Base,1048 const MCOperand &DispMO, unsigned Index,1049 raw_ostream &OS) {1050 printOperand(DispMO, MAI, OS);1051 if (Base || Index) {1052 OS << '(';1053 if (Index) {1054 printFormattedRegName(MAI, Index, OS);1055 if (Base)1056 OS << ',';1057 }1058 if (Base)1059 printFormattedRegName(MAI, Base, OS);1060 OS << ')';1061 }1062}1063 1064bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,1065 const char *ExtraCode,1066 raw_ostream &OS) {1067 const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();1068 const MachineOperand &MO = MI->getOperand(OpNo);1069 MCOperand MCOp;1070 if (ExtraCode) {1071 if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&1072 SystemZ::GR128BitRegClass.contains(MO.getReg()))1073 MCOp =1074 MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));1075 else1076 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);1077 } else {1078 SystemZMCInstLower Lower(MF->getContext(), *this);1079 MCOp = Lower.lowerOperand(MO);1080 }1081 printOperand(MCOp, MAI, OS);1082 return false;1083}1084 1085bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,1086 unsigned OpNo,1087 const char *ExtraCode,1088 raw_ostream &OS) {1089 if (ExtraCode && ExtraCode[0] && !ExtraCode[1]) {1090 switch (ExtraCode[0]) {1091 case 'A':1092 // Unlike EmitMachineNode(), EmitSpecialNode(INLINEASM) does not call1093 // setMemRefs(), so MI->memoperands() is empty and the alignment1094 // information is not available.1095 return false;1096 case 'O':1097 OS << MI->getOperand(OpNo + 1).getImm();1098 return false;1099 case 'R':1100 ::printReg(MI->getOperand(OpNo).getReg(), MAI, OS);1101 return false;1102 }1103 }1104 printAddress(MAI, MI->getOperand(OpNo).getReg(),1105 MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()),1106 MI->getOperand(OpNo + 2).getReg(), OS);1107 return false;1108}1109 1110void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {1111 auto TT = OutContext.getTargetTriple();1112 if (TT.isOSzOS()) {1113 emitADASection();1114 emitIDRLSection(M);1115 }1116 emitAttributes(M);1117 // Emit the END instruction in case of HLASM output. This must be the last1118 // instruction in the source file.1119 getTargetStreamer()->emitEnd();1120}1121 1122void SystemZAsmPrinter::emitADASection() {1123 OutStreamer->pushSection();1124 1125 const unsigned PointerSize = getDataLayout().getPointerSize();1126 OutStreamer->switchSection(getObjFileLowering().getADASection());1127 1128 unsigned EmittedBytes = 0;1129 for (auto &Entry : ADATable.getTable()) {1130 const MCSymbol *Sym;1131 unsigned SlotKind;1132 std::tie(Sym, SlotKind) = Entry.first;1133 unsigned Offset = Entry.second;1134 assert(Offset == EmittedBytes && "Offset not as expected");1135 (void)EmittedBytes;1136#define EMIT_COMMENT(Str) \1137 OutStreamer->AddComment(Twine("Offset ") \1138 .concat(utostr(Offset)) \1139 .concat(" " Str " ") \1140 .concat(Sym->getName()));1141 switch (SlotKind) {1142 case SystemZII::MO_ADA_DIRECT_FUNC_DESC:1143 // Language Environment DLL logic requires function descriptors, for1144 // imported functions, that are placed in the ADA to be 8 byte aligned.1145 EMIT_COMMENT("function descriptor of");1146 OutStreamer->emitValue(1147 MCSpecifierExpr::create(MCSymbolRefExpr::create(Sym, OutContext),1148 SystemZ::S_RCon, OutContext),1149 PointerSize);1150 OutStreamer->emitValue(1151 MCSpecifierExpr::create(MCSymbolRefExpr::create(Sym, OutContext),1152 SystemZ::S_VCon, OutContext),1153 PointerSize);1154 EmittedBytes += PointerSize * 2;1155 break;1156 case SystemZII::MO_ADA_DATA_SYMBOL_ADDR:1157 EMIT_COMMENT("pointer to data symbol");1158 OutStreamer->emitValue(1159 MCSpecifierExpr::create(MCSymbolRefExpr::create(Sym, OutContext),1160 SystemZ::S_None, OutContext),1161 PointerSize);1162 EmittedBytes += PointerSize;1163 break;1164 case SystemZII::MO_ADA_INDIRECT_FUNC_DESC: {1165 MCSymbol *Alias = OutContext.createTempSymbol(1166 Twine(Sym->getName()).concat("@indirect"));1167 OutStreamer->emitAssignment(Alias,1168 MCSymbolRefExpr::create(Sym, OutContext));1169 OutStreamer->emitSymbolAttribute(Alias, MCSA_IndirectSymbol);1170 1171 EMIT_COMMENT("pointer to function descriptor");1172 OutStreamer->emitValue(1173 MCSpecifierExpr::create(MCSymbolRefExpr::create(Alias, OutContext),1174 SystemZ::S_VCon, OutContext),1175 PointerSize);1176 EmittedBytes += PointerSize;1177 break;1178 }1179 default:1180 llvm_unreachable("Unexpected slot kind");1181 }1182#undef EMIT_COMMENT1183 }1184 OutStreamer->popSection();1185}1186 1187static std::string getProductID(Module &M) {1188 std::string ProductID;1189 if (auto *MD = M.getModuleFlag("zos_product_id"))1190 ProductID = cast<MDString>(MD)->getString().str();1191 if (ProductID.empty())1192 ProductID = "LLVM";1193 return ProductID;1194}1195 1196static uint32_t getProductVersion(Module &M) {1197 if (auto *VersionVal = mdconst::extract_or_null<ConstantInt>(1198 M.getModuleFlag("zos_product_major_version")))1199 return VersionVal->getZExtValue();1200 return LLVM_VERSION_MAJOR;1201}1202 1203static uint32_t getProductRelease(Module &M) {1204 if (auto *ReleaseVal = mdconst::extract_or_null<ConstantInt>(1205 M.getModuleFlag("zos_product_minor_version")))1206 return ReleaseVal->getZExtValue();1207 return LLVM_VERSION_MINOR;1208}1209 1210static uint32_t getProductPatch(Module &M) {1211 if (auto *PatchVal = mdconst::extract_or_null<ConstantInt>(1212 M.getModuleFlag("zos_product_patchlevel")))1213 return PatchVal->getZExtValue();1214 return LLVM_VERSION_PATCH;1215}1216 1217static time_t getTranslationTime(Module &M) {1218 std::time_t Time = 0;1219 if (auto *Val = mdconst::extract_or_null<ConstantInt>(1220 M.getModuleFlag("zos_translation_time"))) {1221 long SecondsSinceEpoch = Val->getSExtValue();1222 Time = static_cast<time_t>(SecondsSinceEpoch);1223 }1224 return Time;1225}1226 1227void SystemZAsmPrinter::emitIDRLSection(Module &M) {1228 OutStreamer->pushSection();1229 OutStreamer->switchSection(getObjFileLowering().getIDRLSection());1230 constexpr unsigned IDRLDataLength = 30;1231 std::time_t Time = getTranslationTime(M);1232 1233 uint32_t ProductVersion = getProductVersion(M);1234 uint32_t ProductRelease = getProductRelease(M);1235 1236 std::string ProductID = getProductID(M);1237 1238 SmallString<IDRLDataLength + 1> TempStr;1239 raw_svector_ostream O(TempStr);1240 O << formatv("{0,-10}{1,0-2:d}{2,0-2:d}{3:%Y%m%d%H%M%S}{4,0-2}",1241 ProductID.substr(0, 10).c_str(), ProductVersion, ProductRelease,1242 llvm::sys::toUtcTime(Time), "0");1243 SmallString<IDRLDataLength> Data;1244 ConverterEBCDIC::convertToEBCDIC(TempStr, Data);1245 1246 OutStreamer->emitInt8(0); // Reserved.1247 OutStreamer->emitInt8(3); // Format.1248 OutStreamer->emitInt16(IDRLDataLength); // Length.1249 OutStreamer->emitBytes(Data.str());1250 OutStreamer->popSection();1251}1252 1253void SystemZAsmPrinter::emitFunctionBodyEnd() {1254 if (TM.getTargetTriple().isOSzOS()) {1255 // Emit symbol for the end of function if the z/OS target streamer1256 // is used. This is needed to calculate the size of the function.1257 MCSymbol *FnEndSym = createTempSymbol("func_end");1258 OutStreamer->emitLabel(FnEndSym);1259 1260 OutStreamer->pushSection();1261 OutStreamer->switchSection(getObjFileLowering().getTextSection(),1262 GOFF::SK_PPA1);1263 emitPPA1(FnEndSym);1264 OutStreamer->popSection();1265 1266 CurrentFnPPA1Sym = nullptr;1267 CurrentFnEPMarkerSym = nullptr;1268 }1269}1270 1271static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,1272 bool StackProtector, bool FPRMask, bool VRMask,1273 bool EHBlock, bool HasArgAreaLength, bool HasName) {1274 enum class PPA1Flag1 : uint8_t {1275 DSA64Bit = (0x80 >> 0),1276 VarArg = (0x80 >> 7),1277 LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit)1278 };1279 enum class PPA1Flag2 : uint8_t {1280 ExternalProcedure = (0x80 >> 0),1281 STACKPROTECTOR = (0x80 >> 3),1282 LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure)1283 };1284 enum class PPA1Flag3 : uint8_t {1285 HasArgAreaLength = (0x80 >> 1),1286 FPRMask = (0x80 >> 2),1287 LLVM_MARK_AS_BITMASK_ENUM(HasArgAreaLength)1288 };1289 enum class PPA1Flag4 : uint8_t {1290 EPMOffsetPresent = (0x80 >> 0),1291 VRMask = (0x80 >> 2),1292 EHBlock = (0x80 >> 3),1293 ProcedureNamePresent = (0x80 >> 7),1294 LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent)1295 };1296 1297 // Declare optional section flags that can be modified.1298 auto Flags1 = PPA1Flag1(0);1299 auto Flags2 = PPA1Flag2::ExternalProcedure;1300 auto Flags3 = PPA1Flag3(0);1301 auto Flags4 = PPA1Flag4::EPMOffsetPresent;1302 1303 Flags1 |= PPA1Flag1::DSA64Bit;1304 1305 if (VarArg)1306 Flags1 |= PPA1Flag1::VarArg;1307 1308 if (StackProtector)1309 Flags2 |= PPA1Flag2::STACKPROTECTOR;1310 1311 if (HasArgAreaLength)1312 Flags3 |= PPA1Flag3::HasArgAreaLength; // Add emit ArgAreaLength flag.1313 1314 // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in.1315 if (FPRMask)1316 Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag.1317 1318 if (VRMask)1319 Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag.1320 1321 if (EHBlock)1322 Flags4 |= PPA1Flag4::EHBlock; // Add optional EH block.1323 1324 if (HasName)1325 Flags4 |= PPA1Flag4::ProcedureNamePresent; // Add optional name block.1326 1327 OutStreamer->AddComment("PPA1 Flags 1");1328 if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit)1329 OutStreamer->AddComment(" Bit 0: 1 = 64-bit DSA");1330 else1331 OutStreamer->AddComment(" Bit 0: 0 = 32-bit DSA");1332 if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg)1333 OutStreamer->AddComment(" Bit 7: 1 = Vararg function");1334 OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1.1335 1336 OutStreamer->AddComment("PPA1 Flags 2");1337 if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure)1338 OutStreamer->AddComment(" Bit 0: 1 = External procedure");1339 if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR)1340 OutStreamer->AddComment(" Bit 3: 1 = STACKPROTECT is enabled");1341 else1342 OutStreamer->AddComment(" Bit 3: 0 = STACKPROTECT is not enabled");1343 OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2.1344 1345 OutStreamer->AddComment("PPA1 Flags 3");1346 if ((Flags3 & PPA1Flag3::HasArgAreaLength) == PPA1Flag3::HasArgAreaLength)1347 OutStreamer->AddComment(1348 " Bit 1: 1 = Argument Area Length is in optional area");1349 if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask)1350 OutStreamer->AddComment(" Bit 2: 1 = FP Reg Mask is in optional area");1351 OutStreamer->emitInt8(1352 static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections).1353 1354 OutStreamer->AddComment("PPA1 Flags 4");1355 if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask)1356 OutStreamer->AddComment(" Bit 2: 1 = Vector Reg Mask is in optional area");1357 if ((Flags4 & PPA1Flag4::EHBlock) == PPA1Flag4::EHBlock)1358 OutStreamer->AddComment(" Bit 3: 1 = C++ EH block");1359 if ((Flags4 & PPA1Flag4::ProcedureNamePresent) ==1360 PPA1Flag4::ProcedureNamePresent)1361 OutStreamer->AddComment(" Bit 7: 1 = Name Length and Name");1362 OutStreamer->emitInt8(static_cast<uint8_t>(1363 Flags4)); // Flags 4 (optional sections, always emit these).1364}1365 1366static void emitPPA1Name(std::unique_ptr<MCStreamer> &OutStreamer,1367 StringRef OutName) {1368 size_t NameSize = OutName.size();1369 uint16_t OutSize;1370 if (NameSize < UINT16_MAX) {1371 OutSize = static_cast<uint16_t>(NameSize);1372 } else {1373 OutName = OutName.substr(0, UINT16_MAX);1374 OutSize = UINT16_MAX;1375 }1376 // Emit padding to ensure that the next optional field word-aligned.1377 uint8_t ExtraZeros = 4 - ((2 + OutSize) % 4);1378 1379 SmallString<512> OutnameConv;1380 ConverterEBCDIC::convertToEBCDIC(OutName, OutnameConv);1381 OutName = OutnameConv.str();1382 1383 OutStreamer->AddComment("Length of Name");1384 OutStreamer->emitInt16(OutSize);1385 OutStreamer->AddComment("Name of Function");1386 OutStreamer->emitBytes(OutName);1387 OutStreamer->emitZeros(ExtraZeros);1388}1389 1390void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {1391 assert(PPA2Sym != nullptr && "PPA2 Symbol not defined");1392 1393 const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();1394 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();1395 const auto TargetHasVector = Subtarget.hasVector();1396 1397 const SystemZMachineFunctionInfo *ZFI =1398 MF->getInfo<SystemZMachineFunctionInfo>();1399 const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>(1400 Subtarget.getFrameLowering());1401 const MachineFrameInfo &MFFrame = MF->getFrameInfo();1402 1403 // Get saved GPR/FPR/VPR masks.1404 const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();1405 uint16_t SavedGPRMask = 0;1406 uint16_t SavedFPRMask = 0;1407 uint8_t SavedVRMask = 0;1408 int64_t OffsetFPR = 0;1409 int64_t OffsetVR = 0;1410 const int64_t TopOfStack =1411 MFFrame.getOffsetAdjustment() + MFFrame.getStackSize();1412 1413 // Loop over the spilled registers. The CalleeSavedInfo can't be used because1414 // it does not contain all spilled registers.1415 for (unsigned I = ZFI->getSpillGPRRegs().LowGPR,1416 E = ZFI->getSpillGPRRegs().HighGPR;1417 I && E && I <= E; ++I) {1418 unsigned V = TRI->getEncodingValue((Register)I);1419 assert(V < 16 && "GPR index out of range");1420 SavedGPRMask |= 1 << (15 - V);1421 }1422 1423 for (auto &CS : CSI) {1424 unsigned Reg = CS.getReg();1425 unsigned I = TRI->getEncodingValue(Reg);1426 1427 if (SystemZ::FP64BitRegClass.contains(Reg)) {1428 assert(I < 16 && "FPR index out of range");1429 SavedFPRMask |= 1 << (15 - I);1430 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());1431 if (Temp < OffsetFPR)1432 OffsetFPR = Temp;1433 } else if (SystemZ::VR128BitRegClass.contains(Reg)) {1434 assert(I >= 16 && I <= 23 && "VPR index out of range");1435 unsigned BitNum = I - 16;1436 SavedVRMask |= 1 << (7 - BitNum);1437 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());1438 if (Temp < OffsetVR)1439 OffsetVR = Temp;1440 }1441 }1442 1443 // Adjust the offset.1444 OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0;1445 OffsetVR += (OffsetVR < 0) ? TopOfStack : 0;1446 1447 // Get alloca register.1448 uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF));1449 uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0;1450 assert(AllocaReg < 16 && "Can't have alloca register larger than 15");1451 (void)AllocaReg;1452 1453 // Build FPR save area offset.1454 uint32_t FrameAndFPROffset = 0;1455 if (SavedFPRMask) {1456 uint64_t FPRSaveAreaOffset = OffsetFPR;1457 assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range");1458 1459 FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.1460 FrameAndFPROffset |= FrameReg << 28; // Put into top 4 bits.1461 }1462 1463 // Build VR save area offset.1464 uint32_t FrameAndVROffset = 0;1465 if (TargetHasVector && SavedVRMask) {1466 uint64_t VRSaveAreaOffset = OffsetVR;1467 assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range");1468 1469 FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.1470 FrameAndVROffset |= FrameReg << 28; // Put into top 4 bits.1471 }1472 1473 // Emit PPA1 section.1474 OutStreamer->AddComment("PPA1");1475 OutStreamer->emitLabel(CurrentFnPPA1Sym);1476 OutStreamer->AddComment("Version");1477 OutStreamer->emitInt8(0x02); // Version.1478 OutStreamer->AddComment("LE Signature X'CE'");1479 OutStreamer->emitInt8(0xCE); // CEL signature.1480 OutStreamer->AddComment("Saved GPR Mask");1481 OutStreamer->emitInt16(SavedGPRMask);1482 OutStreamer->AddComment("Offset to PPA2");1483 OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CurrentFnPPA1Sym, 4);1484 1485 bool NeedEmitEHBlock = !MF->getLandingPads().empty();1486 1487 // Optional Argument Area Length.1488 // Note: This represents the length of the argument area that we reserve1489 // in our stack for setting up arguments for calls to other1490 // routines. If this optional field is not set, LE will reserve1491 // 128 bytes for the argument area. This optional field is1492 // created if greater than 128 bytes is required - to guarantee1493 // the required space is reserved on stack extension in the new1494 // extension. This optional field is also created if the1495 // routine has alloca(). This may reduce stack space1496 // if alloca() call causes a stack extension.1497 bool HasArgAreaLength =1498 (AllocaReg != 0) || (MFFrame.getMaxCallFrameSize() > 128);1499 1500 bool HasName =1501 MF->getFunction().hasName() && MF->getFunction().getName().size() > 0;1502 1503 emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(),1504 MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,1505 TargetHasVector && SavedVRMask != 0, NeedEmitEHBlock,1506 HasArgAreaLength, HasName);1507 1508 OutStreamer->AddComment("Length/4 of Parms");1509 OutStreamer->emitInt16(1510 static_cast<uint16_t>(ZFI->getSizeOfFnParams() / 4)); // Parms/4.1511 OutStreamer->AddComment("Length of Code");1512 OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4);1513 1514 if (HasArgAreaLength) {1515 OutStreamer->AddComment("Argument Area Length");1516 OutStreamer->emitInt32(MFFrame.getMaxCallFrameSize());1517 }1518 1519 // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).1520 if (SavedFPRMask) {1521 OutStreamer->AddComment("FPR mask");1522 OutStreamer->emitInt16(SavedFPRMask);1523 OutStreamer->AddComment("AR mask");1524 OutStreamer->emitInt16(0); // AR Mask, unused currently.1525 OutStreamer->AddComment("FPR Save Area Locator");1526 OutStreamer->AddComment(Twine(" Bit 0-3: Register R")1527 .concat(utostr(FrameAndFPROffset >> 28))1528 .str());1529 OutStreamer->AddComment(Twine(" Bit 4-31: Offset ")1530 .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF))1531 .str());1532 OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with1533 // register to add value to1534 // (alloca reg).1535 }1536 1537 // Emit saved VR mask to VR save area.1538 if (TargetHasVector && SavedVRMask) {1539 OutStreamer->AddComment("VR mask");1540 OutStreamer->emitInt8(SavedVRMask);1541 OutStreamer->emitInt8(0); // Reserved.1542 OutStreamer->emitInt16(0); // Also reserved.1543 OutStreamer->AddComment("VR Save Area Locator");1544 OutStreamer->AddComment(Twine(" Bit 0-3: Register R")1545 .concat(utostr(FrameAndVROffset >> 28))1546 .str());1547 OutStreamer->AddComment(Twine(" Bit 4-31: Offset ")1548 .concat(utostr(FrameAndVROffset & 0x0FFFFFFF))1549 .str());1550 OutStreamer->emitInt32(FrameAndVROffset);1551 }1552 1553 // Emit C++ EH information block1554 const Function *Per = nullptr;1555 if (NeedEmitEHBlock) {1556 Per = dyn_cast<Function>(1557 MF->getFunction().getPersonalityFn()->stripPointerCasts());1558 MCSymbol *PersonalityRoutine =1559 Per ? MF->getTarget().getSymbol(Per) : nullptr;1560 assert(PersonalityRoutine && "Missing personality routine");1561 1562 OutStreamer->AddComment("Version");1563 OutStreamer->emitInt32(1);1564 OutStreamer->AddComment("Flags");1565 OutStreamer->emitInt32(0); // LSDA field is a WAS offset1566 OutStreamer->AddComment("Personality routine");1567 OutStreamer->emitInt64(ADATable.insert(1568 PersonalityRoutine, SystemZII::MO_ADA_INDIRECT_FUNC_DESC));1569 OutStreamer->AddComment("LSDA location");1570 MCSymbol *GCCEH = MF->getContext().getOrCreateSymbol(1571 Twine("GCC_except_table") + Twine(MF->getFunctionNumber()));1572 OutStreamer->emitInt64(1573 ADATable.insert(GCCEH, SystemZII::MO_ADA_DATA_SYMBOL_ADDR));1574 }1575 1576 // Emit name length and name optional section (0x01 of flags 4)1577 if (HasName)1578 emitPPA1Name(OutStreamer, MF->getFunction().getName());1579 1580 // Emit offset to entry point optional section (0x80 of flags 4).1581 OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym,1582 4);1583}1584 1585void SystemZAsmPrinter::emitStartOfAsmFile(Module &M) {1586 if (TM.getTargetTriple().isOSzOS())1587 emitPPA2(M);1588 AsmPrinter::emitStartOfAsmFile(M);1589}1590 1591void SystemZAsmPrinter::emitPPA2(Module &M) {1592 OutStreamer->pushSection();1593 OutStreamer->switchSection(getObjFileLowering().getTextSection(),1594 GOFF::SK_PPA2);1595 MCContext &OutContext = OutStreamer->getContext();1596 // Make CELQSTRT symbol.1597 const char *StartSymbolName = "CELQSTRT";1598 MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);1599 1600 // Create symbol and assign to class field for use in PPA1.1601 PPA2Sym = OutContext.createTempSymbol("PPA2", false);1602 MCSymbol *DateVersionSym = OutContext.createTempSymbol("DVS", false);1603 1604 std::time_t Time = getTranslationTime(M);1605 SmallString<15> CompilationTime; // 14 + null1606 raw_svector_ostream O(CompilationTime);1607 O << formatv("{0:%Y%m%d%H%M%S}", llvm::sys::toUtcTime(Time));1608 1609 uint32_t ProductVersion = getProductVersion(M),1610 ProductRelease = getProductRelease(M),1611 ProductPatch = getProductPatch(M);1612 1613 SmallString<7> Version; // 6 + null1614 raw_svector_ostream ostr(Version);1615 ostr << formatv("{0,0-2:d}{1,0-2:d}{2,0-2:d}", ProductVersion, ProductRelease,1616 ProductPatch);1617 1618 // Drop 0 during conversion.1619 SmallString<sizeof(CompilationTime) - 1> CompilationTimeStr;1620 SmallString<sizeof(Version) - 1> VersionStr;1621 1622 ConverterEBCDIC::convertToEBCDIC(CompilationTime, CompilationTimeStr);1623 ConverterEBCDIC::convertToEBCDIC(Version, VersionStr);1624 1625 enum class PPA2MemberId : uint8_t {1626 // See z/OS Language Environment Vendor Interfaces v2r5, p.23, for1627 // complete list. Only the C runtime is supported by this backend.1628 LE_C_Runtime = 3,1629 };1630 enum class PPA2MemberSubId : uint8_t {1631 // List of languages using the LE C runtime implementation.1632 C = 0x00,1633 CXX = 0x01,1634 Swift = 0x03,1635 Go = 0x60,1636 LLVMBasedLang = 0xe7,1637 };1638 // PPA2 Flags1639 enum class PPA2Flags : uint8_t {1640 CompileForBinaryFloatingPoint = 0x80,1641 CompiledWithXPLink = 0x01,1642 CompiledUnitASCII = 0x04,1643 HasServiceInfo = 0x20,1644 };1645 1646 PPA2MemberSubId MemberSubId = PPA2MemberSubId::LLVMBasedLang;1647 if (auto *MD = M.getModuleFlag("zos_cu_language")) {1648 StringRef Language = cast<MDString>(MD)->getString();1649 MemberSubId = StringSwitch<PPA2MemberSubId>(Language)1650 .Case("C", PPA2MemberSubId::C)1651 .Case("C++", PPA2MemberSubId::CXX)1652 .Case("Swift", PPA2MemberSubId::Swift)1653 .Case("Go", PPA2MemberSubId::Go)1654 .Default(PPA2MemberSubId::LLVMBasedLang);1655 }1656 1657 // Emit PPA2 section.1658 OutStreamer->emitLabel(PPA2Sym);1659 OutStreamer->emitInt8(static_cast<uint8_t>(PPA2MemberId::LE_C_Runtime));1660 OutStreamer->emitInt8(static_cast<uint8_t>(MemberSubId));1661 OutStreamer->emitInt8(0x22); // Member defined, c370_plist+c370_env1662 OutStreamer->emitInt8(0x04); // Control level 4 (XPLink)1663 OutStreamer->emitAbsoluteSymbolDiff(CELQSTRT, PPA2Sym, 4);1664 OutStreamer->emitInt32(0x00000000);1665 OutStreamer->emitAbsoluteSymbolDiff(DateVersionSym, PPA2Sym, 4);1666 OutStreamer->emitInt32(1667 0x00000000); // Offset to main entry point, always 0 (so says TR).1668 uint8_t Flgs = static_cast<uint8_t>(PPA2Flags::CompileForBinaryFloatingPoint);1669 Flgs |= static_cast<uint8_t>(PPA2Flags::CompiledWithXPLink);1670 1671 if (auto *MD = M.getModuleFlag("zos_le_char_mode")) {1672 const StringRef &CharMode = cast<MDString>(MD)->getString();1673 if (CharMode == "ascii") {1674 Flgs |= static_cast<uint8_t>(1675 PPA2Flags::CompiledUnitASCII); // Setting bit for ASCII char. mode.1676 } else if (CharMode != "ebcdic") {1677 report_fatal_error(1678 "Only ascii or ebcdic are valid values for zos_le_char_mode "1679 "metadata");1680 }1681 }1682 1683 OutStreamer->emitInt8(Flgs);1684 OutStreamer->emitInt8(0x00); // Reserved.1685 // No MD5 signature before timestamp.1686 // No FLOAT(AFP(VOLATILE)).1687 // Remaining 5 flag bits reserved.1688 OutStreamer->emitInt16(0x0000); // 16 Reserved flag bits.1689 1690 // Emit date and version section.1691 OutStreamer->emitLabel(DateVersionSym);1692 OutStreamer->emitBytes(CompilationTimeStr.str());1693 OutStreamer->emitBytes(VersionStr.str());1694 1695 OutStreamer->emitInt16(0x0000); // Service level string length.1696 1697 // The binder requires that the offset to the PPA2 be emitted in a different,1698 // specially-named section.1699 OutStreamer->switchSection(getObjFileLowering().getPPA2ListSection());1700 // Emit 8 byte alignment.1701 // Emit pointer to PPA2 label.1702 OutStreamer->AddComment("A(PPA2-CELQSTRT)");1703 OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CELQSTRT, 8);1704 OutStreamer->popSection();1705}1706 1707void SystemZAsmPrinter::emitFunctionEntryLabel() {1708 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();1709 1710 if (Subtarget.getTargetTriple().isOSzOS()) {1711 MCContext &OutContext = OutStreamer->getContext();1712 1713 // Save information for later use.1714 std::string N(MF->getFunction().hasName()1715 ? Twine(MF->getFunction().getName()).concat("_").str()1716 : "");1717 1718 CurrentFnEPMarkerSym =1719 OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true);1720 CurrentFnPPA1Sym =1721 OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true);1722 1723 // EntryPoint Marker1724 const MachineFrameInfo &MFFrame = MF->getFrameInfo();1725 bool IsUsingAlloca = MFFrame.hasVarSizedObjects();1726 uint32_t DSASize = MFFrame.getStackSize();1727 bool IsLeaf = DSASize == 0 && MFFrame.getCalleeSavedInfo().empty();1728 1729 // Set Flags.1730 uint8_t Flags = 0;1731 if (IsLeaf)1732 Flags |= 0x08;1733 if (IsUsingAlloca)1734 Flags |= 0x04;1735 1736 // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.1737 uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 51738 DSAAndFlags |= Flags;1739 1740 // Emit entry point marker section.1741 OutStreamer->AddComment("XPLINK Routine Layout Entry");1742 OutStreamer->emitLabel(CurrentFnEPMarkerSym);1743 OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");1744 OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.1745 OutStreamer->AddComment("Mark Type C'1'");1746 OutStreamer->emitInt8(0xF1); // Mark Type.1747 OutStreamer->AddComment("Offset to PPA1");1748 OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym,1749 4);1750 if (OutStreamer->isVerboseAsm()) {1751 OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));1752 OutStreamer->AddComment("Entry Flags");1753 if (Flags & 0x08)1754 OutStreamer->AddComment(" Bit 1: 1 = Leaf function");1755 else1756 OutStreamer->AddComment(" Bit 1: 0 = Non-leaf function");1757 if (Flags & 0x04)1758 OutStreamer->AddComment(" Bit 2: 1 = Uses alloca");1759 else1760 OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca");1761 }1762 OutStreamer->emitInt32(DSAAndFlags);1763 }1764 1765 AsmPrinter::emitFunctionEntryLabel();1766}1767 1768char SystemZAsmPrinter::ID = 0;1769 1770INITIALIZE_PASS(SystemZAsmPrinter, "systemz-asm-printer",1771 "SystemZ Assembly Printer", false, false)1772 1773// Force static initialization.1774extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void1775LLVMInitializeSystemZAsmPrinter() {1776 RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());1777}1778