brintos

brintos / llvm-project-archived public Read only

0
0
Text · 62.2 KiB · f061272 Raw
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