LLVM 24.0.0git
SystemZXPLINKAsmPrinter.cpp
Go to the documentation of this file.
1//===-- SystemZXPLINKAsmPrinter.cpp - SystemZ XPLINK asm printer ----------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the SystemZXPLINKAsmPrinter class.
10//
11//===----------------------------------------------------------------------===//
12
17#include "SystemZInstrInfo.h"
18#include "SystemZMCInstLower.h"
20#include "SystemZSubtarget.h"
26#include "llvm/IR/Function.h"
27#include "llvm/IR/GlobalAlias.h"
29#include "llvm/IR/Module.h"
30#include "llvm/MC/MCExpr.h"
33#include "llvm/Support/Chrono.h"
36
37using namespace llvm;
38
43
45 SM.reset();
46
47 // In HLASM, the only way to represent aliases is to use the
48 // extra-label-at-definition strategy. This is similar to the AIX
49 // implementation with the additional caveat that all symbol attributes must
50 // be emitted before the label is emitted.
51 // Construct an aliasing list for each GlobalObject.
52 for (const auto &Alias : M.aliases()) {
53 const GlobalObject *Aliasee = Alias.getAliaseeObject();
54 if (!Aliasee)
55 OutContext.reportError(
56 {}, "Alias without a base object is not yet supported on z/OS.");
57
58 bool IsFunc = isa<Function>(Aliasee->stripPointerCasts());
59 if (IsFunc) {
60 if (Alias.hasWeakLinkage() || Alias.hasLinkOnceLinkage())
61 OutContext.reportError({},
62 "Weak alias/reference not supported on z/OS");
63
64 GOAliasMap[Aliasee].push_back(&Alias);
65 } else
66 OutContext.reportError({},
67 "Only aliases to functions is supported in GOFF.");
68 }
70}
71
72// The XPLINK ABI requires that a no-op encoding the call type is emitted after
73// each call to a subroutine. This information can be used by the called
74// function to determine its entry point, e.g. for generating a backtrace. The
75// call type is encoded as a register number in the bcr instruction. See
76// enumeration CallType for the possible values.
77void SystemZXPLINKAsmPrinter::emitCallInformation(CallType CT) {
79 MCInstBuilder(SystemZ::BCRAsm)
80 .addImm(0)
81 .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
82}
83
85SystemZXPLINKAsmPrinter::AssociatedDataAreaTable::insert(const MCSymbol *Sym,
86 unsigned SlotKind) {
87 auto Key = std::make_pair(Sym, SlotKind);
88 auto It = Displacements.find(Key);
89
90 if (It != Displacements.end())
91 return (*It).second;
92
93 // Determine length of descriptor.
95 switch (SlotKind) {
97 Length = 2 * PointerSize;
98 break;
99 default:
100 Length = PointerSize;
101 break;
102 }
103
104 uint32_t Displacement = NextDisplacement;
105 Displacements[std::make_pair(Sym, SlotKind)] = NextDisplacement;
106 NextDisplacement += Length;
107
108 return Displacement;
109}
110
111uint32_t SystemZXPLINKAsmPrinter::AssociatedDataAreaTable::insert(
112 const MachineOperand MO) {
113 MCSymbol *Sym;
115 const GlobalValue *GV = MO.getGlobal();
116 Sym = MO.getParent()->getMF()->getTarget().getSymbol(GV);
117 assert(Sym && "No symbol");
118 } else if (MO.getType() == MachineOperand::MO_ExternalSymbol) {
119 const char *SymName = MO.getSymbolName();
120 Sym = MO.getParent()->getMF()->getContext().getOrCreateSymbol(SymName);
121 assert(Sym && "No symbol");
122 } else
123 llvm_unreachable("Unexpected operand type");
124
125 unsigned ADAslotType = MO.getTargetFlags();
126 return insert(Sym, ADAslotType);
127}
128
130 SystemZMCInstLower Lower(MF->getContext(), *this);
131 MCInst LoweredMI;
132
133 switch (MI->getOpcode()) {
134 case SystemZ::CallBRASL_XPLINK64:
136 .addReg(SystemZ::R7D)
137 .addExpr(Lower.getExpr(MI->getOperand(0),
139 emitCallInformation(CallType::BRASL7);
140 return;
141
142 case SystemZ::CallBASR_XPLINK64:
144 .addReg(SystemZ::R7D)
145 .addReg(MI->getOperand(0).getReg()));
146 emitCallInformation(CallType::BASR76);
147 return;
148
149 case SystemZ::Return_XPLINK:
150 LoweredMI =
151 MCInstBuilder(SystemZ::B).addReg(SystemZ::R7D).addImm(2).addReg(0);
152 break;
153
154 case SystemZ::CondReturn_XPLINK:
155 LoweredMI = MCInstBuilder(SystemZ::BC)
156 .addImm(MI->getOperand(0).getImm())
157 .addImm(MI->getOperand(1).getImm())
158 .addReg(SystemZ::R7D)
159 .addImm(2)
160 .addReg(0);
161 break;
162
163 case SystemZ::CallBASR_STACKEXT:
165 .addReg(SystemZ::R3D)
166 .addReg(MI->getOperand(0).getReg()));
167 emitCallInformation(CallType::BASR33);
168 return;
169
170 case SystemZ::ADA_ENTRY_VALUE:
171 case SystemZ::ADA_ENTRY: {
172 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
173 const SystemZInstrInfo *TII = Subtarget.getInstrInfo();
174 uint32_t Disp = ADATable.insert(MI->getOperand(1));
175 Register TargetReg = MI->getOperand(0).getReg();
176
177 Register ADAReg = MI->getOperand(2).getReg();
178 Disp += MI->getOperand(3).getImm();
179 bool LoadAddr = MI->getOpcode() == SystemZ::ADA_ENTRY;
180
181 unsigned Op0 = LoadAddr ? SystemZ::LA : SystemZ::LG;
182 unsigned Op = TII->getOpcodeForOffset(Op0, Disp);
183
184 Register IndexReg = 0;
185 if (!Op) {
186 if (TargetReg != ADAReg) {
187 IndexReg = TargetReg;
188 // Use TargetReg to store displacement.
191 MCInstBuilder(SystemZ::LLILF).addReg(TargetReg).addImm(Disp));
192 } else
194 .addReg(TargetReg)
195 .addReg(TargetReg)
196 .addImm(Disp));
197 Disp = 0;
198 Op = Op0;
199 }
202 MCInstBuilder(Op).addReg(TargetReg).addReg(ADAReg).addImm(Disp).addReg(
203 IndexReg));
204 return;
205 }
206
207 default:
209 return;
210 }
211 EmitToStreamer(*OutStreamer, LoweredMI);
212}
213
215 const Constant *List,
216 bool IsCtor) {
217 assert(TM.getTargetTriple().isOSBinFormatGOFF() && "Only GOFF supported");
218
219 SmallVector<Structor, 8> Structors;
220 preprocessXXStructorList(DL, List, Structors);
221 if (Structors.empty())
222 return;
223
224 const Align Align = llvm::Align(4);
226 static_cast<const TargetLoweringObjectFileGOFF &>(getObjFileLowering());
227 for (Structor &S : Structors) {
228 MCSectionGOFF *Section =
229 static_cast<MCSectionGOFF *>(Obj.getStaticXtorSection(S.Priority));
230 OutStreamer->switchSection(Section);
231 if (OutStreamer->getCurrentSection() != OutStreamer->getPreviousSection())
233
234 // The priority is provided as an input to getStaticXtorSection(), and is
235 // recalculated within that function as `Prio` going to going into the
236 // PR section.
237 // This priority retrieved via the `SortKey` below is the recalculated
238 // Priority.
239 uint32_t XtorPriority = Section->getPRAttributes().SortKey;
240
241 const GlobalValue *GV = dyn_cast<GlobalValue>(S.Func->stripPointerCasts());
242 assert(GV && "C++ xxtor pointer was not a GlobalValue!");
243 MCSymbolGOFF *Symbol = static_cast<MCSymbolGOFF *>(getSymbol(GV));
244
245 // @@SQINIT entry: { unsigned prio; void (*ctor)(); void (*dtor)(); }
246
247 unsigned PointerSizeInBytes = DL.getPointerSize();
248
249 auto &Ctx = OutStreamer->getContext();
250 const MCExpr *ADAFuncRefExpr;
251 unsigned SlotKind = SystemZII::MO_ADA_DIRECT_FUNC_DESC;
252
253 MCSectionGOFF *ADASection =
254 static_cast<MCSectionGOFF *>(Obj.getADASection());
255 assert(ADASection && "ADA section must exist for GOFF targets!");
256 const MCSymbol *ADASym = ADASection->getBeginSymbol();
257 assert(ADASym && "ADA symbol should already be set!");
258
259 ADAFuncRefExpr = MCBinaryExpr::createAdd(
262 MCConstantExpr::create(ADATable.insert(Symbol, SlotKind), Ctx), Ctx);
263
264 emitInt32(XtorPriority);
265 if (IsCtor) {
266 OutStreamer->emitValue(ADAFuncRefExpr, PointerSizeInBytes);
267 OutStreamer->emitIntValue(0, PointerSizeInBytes);
268 } else {
269 OutStreamer->emitIntValue(0, PointerSizeInBytes);
270 OutStreamer->emitValue(ADAFuncRefExpr, PointerSizeInBytes);
271 }
272 }
273}
274
276 auto *ZOS = getTargetStreamer();
277 emitADASection();
278 emitIDRLSection(M);
279 // On z/OS, we need to associate an external data reference with an ED
280 // symbol, for which we use the the ED of the ADA. We also need to mark the
281 // reference as being to data, otherwise we cannot bind with code generated
282 // by XL.
283 for (auto &GO : M.global_objects()) {
284 if (auto *GV = dyn_cast<GlobalVariable>(&GO)) {
285 if (!GV->hasInitializer()) {
286 MCSymbol *Sym = getSymbol(GV);
287 ZOS->emitADA(Sym, OutContext.getObjectFileInfo()->getADASection());
288 OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeObject);
289 }
290 }
291 }
292}
293
294void SystemZXPLINKAsmPrinter::emitADASection() {
295 OutStreamer->pushSection();
296
297 const unsigned PointerSize = getDataLayout().getPointerSize();
298 OutStreamer->switchSection(getObjFileLowering().getADASection());
299
300 auto *ZOS = getTargetStreamer();
301 unsigned EmittedBytes = 0;
302 for (auto &Entry : ADATable.getTable()) {
303 const MCSymbol *Sym;
304 unsigned SlotKind;
305 std::tie(Sym, SlotKind) = Entry.first;
306 unsigned Offset = Entry.second;
307 assert(Offset == EmittedBytes && "Offset not as expected");
308 (void)EmittedBytes;
309#define EMIT_COMMENT(Str) \
310 OutStreamer->AddComment(Twine("Offset ") \
311 .concat(utostr(Offset)) \
312 .concat(" " Str " ") \
313 .concat(Sym->getName()));
314 switch (SlotKind) {
316 // Language Environment DLL logic requires function descriptors, for
317 // imported functions, that are placed in the ADA to be 8 byte aligned.
318 EMIT_COMMENT("function descriptor of");
319 OutStreamer->emitValue(
322 PointerSize);
323 OutStreamer->emitValue(
326 PointerSize);
327 EmittedBytes += PointerSize * 2;
328 break;
330 EMIT_COMMENT("pointer to data symbol");
331 OutStreamer->emitValue(
334 PointerSize);
335 EmittedBytes += PointerSize;
336 break;
339 Twine(Sym->getName()).concat("@indirect"));
340 OutStreamer->emitSymbolAttribute(Alias, MCSA_IndirectSymbol);
341 OutStreamer->emitSymbolAttribute(Alias, MCSA_ELF_TypeFunction);
342 OutStreamer->emitSymbolAttribute(Alias, MCSA_Global);
343 OutStreamer->emitSymbolAttribute(Alias, MCSA_Extern);
344 MCSymbolGOFF *GOFFSym =
345 static_cast<llvm::MCSymbolGOFF *>(const_cast<llvm::MCSymbol *>(Sym));
346 ZOS->emitExternalName(Alias, GOFFSym->getExternalName());
347 EMIT_COMMENT("pointer to function descriptor");
348 OutStreamer->emitValue(
351 PointerSize);
352 EmittedBytes += PointerSize;
353 break;
354 }
355 default:
356 llvm_unreachable("Unexpected slot kind");
357 }
358#undef EMIT_COMMENT
359 }
360 OutStreamer->popSection();
361}
362
363static std::string getProductID(Module &M) {
364 std::string ProductID;
365 if (auto *MD = M.getModuleFlag("zos_product_id"))
366 ProductID = cast<MDString>(MD)->getString().str();
367 if (ProductID.empty())
368 ProductID = "LLVM";
369 return ProductID;
370}
371
373 if (auto *VersionVal = mdconst::extract_or_null<ConstantInt>(
374 M.getModuleFlag("zos_product_major_version")))
375 return VersionVal->getZExtValue();
376 return LLVM_VERSION_MAJOR;
377}
378
380 if (auto *ReleaseVal = mdconst::extract_or_null<ConstantInt>(
381 M.getModuleFlag("zos_product_minor_version")))
382 return ReleaseVal->getZExtValue();
383 return LLVM_VERSION_MINOR;
384}
385
387 if (auto *PatchVal = mdconst::extract_or_null<ConstantInt>(
388 M.getModuleFlag("zos_product_patchlevel")))
389 return PatchVal->getZExtValue();
390 return LLVM_VERSION_PATCH;
391}
392
393static time_t getTranslationTime(Module &M) {
394 std::time_t Time = 0;
396 M.getModuleFlag("zos_translation_time"))) {
397 long SecondsSinceEpoch = Val->getSExtValue();
398 Time = static_cast<time_t>(SecondsSinceEpoch);
399 }
400 return Time;
401}
402
403void SystemZXPLINKAsmPrinter::emitIDRLSection(Module &M) {
404 OutStreamer->pushSection();
405 OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
406 constexpr unsigned IDRLDataLength = 30;
407 std::time_t Time = getTranslationTime(M);
408
409 uint32_t ProductVersion = getProductVersion(M);
410 uint32_t ProductRelease = getProductRelease(M);
411
412 std::string ProductID = getProductID(M);
413
414 SmallString<IDRLDataLength + 1> TempStr;
415 raw_svector_ostream O(TempStr);
416 O << formatv("{0,-10}{1,0-2:d}{2,0-2:d}{3:%Y%m%d%H%M%S}{4,0-2}",
417 ProductID.substr(0, 10).c_str(), ProductVersion, ProductRelease,
418 llvm::sys::toUtcTime(Time), "0");
419 SmallString<IDRLDataLength> Data;
421
422 OutStreamer->emitInt8(0); // Reserved.
423 OutStreamer->emitInt8(3); // Format.
424 OutStreamer->emitInt16(IDRLDataLength); // Length.
425 OutStreamer->emitBytes(Data.str());
426 OutStreamer->popSection();
427}
428
430 // Emit symbol for the end of function if the z/OS target streamer
431 // is used. This is needed to calculate the size of the function.
432 auto *ZOS = getTargetStreamer();
433 OutStreamer->emitLabel(ZOS->DeferredPPA1.back().FnEnd);
434}
435
436// Determine the end of the prolog and the instructions which updates the stack
437// register, and attach symbols to those instructions.
439 MCSymbol *&EndOfPrologSym,
440 MCSymbol *&StackUpdateSym) {
441 EndOfPrologSym = nullptr;
442 StackUpdateSym = nullptr;
443
444 // Scan the basic block for the FENCE instruction which marks the end
445 // of the prologue. We know
446 // the prologue is spread at most across the first 3 basic blocks. Also record
447 // the first instruction updating the stack pointer.
450 MachineInstr *EndOfPrologMI = nullptr;
451 MachineInstr *StackUpdateMI = nullptr;
452 unsigned BBCount = 1;
453
454 for (auto &MBB : *MF) {
455 for (auto &I : MBB) {
456 if (I.getOpcode() == SystemZ::FENCE)
457 EndOfPrologMI = &I;
458 else if (!StackUpdateMI) {
459 unsigned Opcode = I.getOpcode();
460 // TODO: We can instead emit a pseudo instruction in
461 // SystemZFrameLowering to represent a stack adjustment instruction, and
462 // check for that here, instead of having to check for multiple
463 // instructions.
464 if ((Opcode == SystemZ::AGHI || Opcode == SystemZ::AGFI) &&
465 I.getOperand(0).getReg() == Regs.getStackPointerRegister())
466 StackUpdateMI = &I;
467 }
468 }
469
470 // Prologue can be a max of 3 BBs if we need to call stack extension code
471 if (EndOfPrologMI || BBCount == 3)
472 break;
473
474 ++BBCount;
475 }
476
477 // Leaf functions do not have a prologue.
478 if (EndOfPrologMI == nullptr)
479 return;
480
481#ifdef EXPENSIVE_CHECKS
482 // Check that the prolog length is valid.
483 auto *TII = STI.getInstrInfo();
484 size_t Size = 0;
485
486 for (auto &MBB : *MF) {
487 bool TerminateLoop = false;
488 for (auto &I : MBB) {
489 Size += TII->getInstSizeInBytes(I);
490 if (&I == EndOfPrologMI) {
491 TerminateLoop = true;
492 break;
493 }
494 }
495 if (TerminateLoop)
496 break;
497 }
498 if (Size > 128)
500 Twine(MF->getName()).concat(": Prolog exceeds 128 bytes"));
501#endif
502
503 // Attach a temporary symbol to mark the end of the prolog.
504 EndOfPrologSym = MF->getContext().createTempSymbol("end_of_prologue");
505 EndOfPrologMI->setPostInstrSymbol(*MF, EndOfPrologSym);
506
507 if (StackUpdateMI) {
508 StackUpdateSym = MF->getContext().createTempSymbol("stack_update");
509 StackUpdateMI->setPreInstrSymbol(*MF, StackUpdateSym);
510 }
511}
512
513void SystemZXPLINKAsmPrinter::calculatePPA1() {
514 auto *ZOS = getTargetStreamer();
515 assert(ZOS->PPA2Sym != nullptr && "PPA2 Symbol not defined");
516
517 SystemZTargetzOSStreamer::PPA1Info Info;
518
519 const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
520 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
521
522 const SystemZMachineFunctionInfo *ZFI =
523 MF->getInfo<SystemZMachineFunctionInfo>();
524 const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>(
525 Subtarget.getFrameLowering());
526 const MachineFrameInfo &MFFrame = MF->getFrameInfo();
527
528 // Get saved GPR/FPR/VPR masks.
529 const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
530 uint16_t SavedGPRMask = 0;
531 uint16_t SavedFPRMask = 0;
532 uint8_t SavedVRMask = 0;
533 int64_t OffsetFPR = 0;
534 int64_t OffsetVR = 0;
535 const int64_t TopOfStack =
536 MFFrame.getOffsetAdjustment() + MFFrame.getStackSize();
537
538 // Loop over the spilled registers. The CalleeSavedInfo can't be used because
539 // it does not contain all spilled registers.
540 for (unsigned I = ZFI->getSpillGPRRegs().LowGPR,
541 E = ZFI->getSpillGPRRegs().HighGPR;
542 I && E && I <= E; ++I) {
543 unsigned V = TRI->getEncodingValue((Register)I);
544 assert(V < 16 && "GPR index out of range");
545 SavedGPRMask |= 1 << (15 - V);
546 }
547
548 for (auto &CS : CSI) {
549 unsigned Reg = CS.getReg();
550 unsigned I = TRI->getEncodingValue(Reg);
551
552 if (SystemZ::FP64BitRegClass.contains(Reg)) {
553 assert(I < 16 && "FPR index out of range");
554 SavedFPRMask |= 1 << (15 - I);
555 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
556 if (Temp < OffsetFPR)
557 OffsetFPR = Temp;
558 } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
559 assert(I >= 16 && I <= 23 && "VPR index out of range");
560 unsigned BitNum = I - 16;
561 SavedVRMask |= 1 << (7 - BitNum);
562 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
563 if (Temp < OffsetVR)
564 OffsetVR = Temp;
565 }
566 }
567
568 // Adjust the offset.
569 OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0;
570 OffsetVR += (OffsetVR < 0) ? TopOfStack : 0;
571
572 // Get alloca register.
573 uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF));
574 uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0;
575 assert(AllocaReg < 16 && "Can't have alloca register larger than 15");
576
577 MCSymbol *PersonalityRoutine = nullptr;
578 MCSymbol *GCCEH = nullptr;
579 uint64_t PersonalityADADisp = 0;
580 uint64_t GCCEHADADisp = 0;
581 if (!MF->getLandingPads().empty()) {
582 const Function *Per = dyn_cast<Function>(
583 MF->getFunction().getPersonalityFn()->stripPointerCasts());
584 PersonalityRoutine = Per ? MF->getTarget().getSymbol(Per) : nullptr;
585 if (PersonalityRoutine) {
586 GCCEH = MF->getContext().getOrCreateSymbol(
587 Twine("GCC_except_table") + Twine(MF->getFunctionNumber()));
588 PersonalityADADisp = ADATable.insert(
589 PersonalityRoutine, SystemZII::MO_ADA_INDIRECT_FUNC_DESC);
590 GCCEHADADisp = ADATable.insert(GCCEH, SystemZII::MO_ADA_DATA_SYMBOL_ADDR);
591 }
592 }
593
594 // Get the name of the function, with suffix _.
595 std::string N(MF->getFunction().hasName()
596 ? Twine(MF->getFunction().getName()).concat("_").str()
597 : "");
598
599 // Calculate the lables for the prolog size and the stack update symbol.
600 MCSymbol *EndOfPrologSym;
601 MCSymbol *StackUpdateSym;
602 determinePrologueStackUpdateSym(MF, EndOfPrologSym, StackUpdateSym);
603
604 // Save the calculated values.
605 if (MF->getFunction().hasFnAttribute("zos-ppa1-name"))
606 Info.Name =
607 MF->getFunction().getFnAttribute("zos-ppa1-name").getValueAsString();
608 else if (MF->getFunction().hasName())
609 Info.Name = MF->getFunction().getName();
610
611 Info.PPA1 = OutContext.createTempSymbol(Twine("PPA1_").concat(N), true);
612 Info.EPMarker = OutContext.createTempSymbol(Twine("EPM_").concat(N), true);
613 Info.FnEnd = OutContext.createTempSymbol(Twine(N).concat("end_"));
614 Info.Fn = CurrentFnSym;
615 Info.EndOfProlog = EndOfPrologSym;
616 Info.StackUpdate = StackUpdateSym;
617 Info.PersonalityADADisp = PersonalityADADisp;
618 Info.GCCEHADADisp = GCCEHADADisp;
619 Info.OffsetFPR = OffsetFPR;
620 Info.OffsetVR = OffsetVR;
621 Info.CallFrameSize = MFFrame.getMaxCallFrameSize();
622 Info.SizeOfFnParams = ZFI->getSizeOfFnParams();
623 Info.SavedGPRMask = SavedGPRMask;
624 Info.SavedFPRMask = SavedFPRMask;
625 Info.SavedVRMask = SavedVRMask;
626 Info.FrameReg = FrameReg;
627 Info.AllocaReg = AllocaReg;
628 Info.IsVarArg = MF->getFunction().isVarArg();
629 Info.HasStackProtector = MFFrame.hasStackProtectorIndex();
630
631 ZOS->DeferredPPA1.push_back(Info);
632}
633
638
639void SystemZXPLINKAsmPrinter::emitPPA2(Module &M) {
640 auto *ZOS = getTargetStreamer();
641 OutStreamer->pushSection();
642 OutStreamer->switchSection(getObjFileLowering().getTextSection());
643 MCContext &OutContext = OutStreamer->getContext();
644 // Make CELQSTRT symbol.
645 const char *StartSymbolName = "CELQSTRT";
646 MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);
647 OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_OSLinkage);
648 OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_Global);
649
650 // Create symbol and assign to streamer field for use in PPA1.
651 ZOS->PPA2Sym = OutContext.createTempSymbol("PPA2", false);
652 MCSymbol *PPA2Sym = ZOS->PPA2Sym;
653 MCSymbol *DateVersionSym = OutContext.createTempSymbol("DVS", false);
654
655 std::time_t Time = getTranslationTime(M);
656 SmallString<14> CompilationTimeEBCDIC, CompilationTime;
657 CompilationTime = formatv("{0:%Y%m%d%H%M%S}", llvm::sys::toUtcTime(Time));
658
659 uint32_t ProductVersion = getProductVersion(M),
660 ProductRelease = getProductRelease(M),
661 ProductPatch = getProductPatch(M);
662
663 SmallString<6> VersionEBCDIC, Version;
664 Version = formatv("{0,0-2:d}{1,0-2:d}{2,0-2:d}", ProductVersion,
665 ProductRelease, ProductPatch);
666
667 ConverterEBCDIC::convertToEBCDIC(CompilationTime, CompilationTimeEBCDIC);
669
670 enum class PPA2MemberId : uint8_t {
671 // See z/OS Language Environment Vendor Interfaces v2r5, p.23, for
672 // complete list. Only the C runtime is supported by this backend.
673 LE_C_Runtime = 3,
674 };
675 enum class PPA2MemberSubId : uint8_t {
676 // List of languages using the LE C runtime implementation.
677 C = 0x00,
678 CXX = 0x01,
679 Swift = 0x03,
680 Go = 0x60,
681 LLVMBasedLang = 0xe7,
682 };
683 // PPA2 Flags
684 enum class PPA2Flags : uint8_t {
685 CompileForBinaryFloatingPoint = 0x80,
686 CompiledWithXPLink = 0x01,
687 CompiledUnitASCII = 0x04,
688 HasServiceInfo = 0x20,
689 };
690
691 PPA2MemberSubId MemberSubId = PPA2MemberSubId::LLVMBasedLang;
692 if (auto *MD = M.getModuleFlag("zos_cu_language")) {
693 StringRef Language = cast<MDString>(MD)->getString();
694 MemberSubId = StringSwitch<PPA2MemberSubId>(Language)
695 .Case("C", PPA2MemberSubId::C)
696 .Case("C++", PPA2MemberSubId::CXX)
697 .Case("Swift", PPA2MemberSubId::Swift)
698 .Case("Go", PPA2MemberSubId::Go)
699 .Default(PPA2MemberSubId::LLVMBasedLang);
700 }
701
702 // Emit PPA2 section.
703 OutStreamer->emitLabel(PPA2Sym);
704 OutStreamer->emitInt8(static_cast<uint8_t>(PPA2MemberId::LE_C_Runtime));
705 OutStreamer->emitInt8(static_cast<uint8_t>(MemberSubId));
706 OutStreamer->emitInt8(0x22); // Member defined, c370_plist+c370_env
707 OutStreamer->emitInt8(0x04); // Control level 4 (XPLink)
708 OutStreamer->emitAbsoluteSymbolDiff(CELQSTRT, PPA2Sym, 4);
709 OutStreamer->emitInt32(0x00000000);
710 OutStreamer->emitAbsoluteSymbolDiff(DateVersionSym, PPA2Sym, 4);
711 OutStreamer->emitInt32(
712 0x00000000); // Offset to main entry point, always 0 (so says TR).
713 uint8_t Flgs = static_cast<uint8_t>(PPA2Flags::CompileForBinaryFloatingPoint);
714 Flgs |= static_cast<uint8_t>(PPA2Flags::CompiledWithXPLink);
715
716 bool IsASCII = true;
717 if (auto *MD = M.getModuleFlag("zos_le_char_mode")) {
718 const StringRef &CharMode = cast<MDString>(MD)->getString();
719 if (CharMode == "ebcdic")
720 IsASCII = false;
721 else if (CharMode != "ascii")
722 OutContext.reportError(
723 {}, "Only ascii or ebcdic are allowed for zos_le_char_mode");
724 }
725 if (IsASCII)
726 Flgs |= static_cast<uint8_t>(
727 PPA2Flags::CompiledUnitASCII); // Setting bit for ASCII char. mode.
728
729 OutStreamer->emitInt8(Flgs);
730 OutStreamer->emitInt8(0x00); // Reserved.
731 // No MD5 signature before timestamp.
732 // No FLOAT(AFP(VOLATILE)).
733 // Remaining 5 flag bits reserved.
734 OutStreamer->emitInt16(0x0000); // 16 Reserved flag bits.
735
736 // Emit date and version section.
737 OutStreamer->emitLabel(DateVersionSym);
738 OutStreamer->emitBytes(CompilationTimeEBCDIC.str());
739 OutStreamer->emitBytes(VersionEBCDIC.str());
740
741 OutStreamer->emitInt16(0x0000); // Service level string length.
742
743 // The binder requires that the offset to the PPA2 be emitted in a different,
744 // specially-named section.
745 OutStreamer->switchSection(getObjFileLowering().getPPA2ListSection());
746 // Emit 8 byte alignment.
747 // Emit pointer to PPA2 label.
748 OutStreamer->AddComment("A(PPA2-CELQSTRT)");
749 OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CELQSTRT, 8);
750 OutStreamer->popSection();
751}
752
754 const GlobalAlias &GA) {
755 if (!TM.getTargetTriple().isOSzOS())
756 return AsmPrinter::emitGlobalAlias(M, GA);
757
758 // Aliased function labels have already been emitted for z/OS
759}
760
762 const Constant *BaseCV,
763 uint64_t Offset) {
764 const GlobalAlias *GA = dyn_cast<GlobalAlias>(CV);
766 const Function *FV = dyn_cast<Function>(CV);
767 bool IsFunc = !GV && (FV || (GA && isa<Function>(GA->getAliaseeObject())));
768
769 MCSymbol *Sym = NULL;
770
771 if (GA)
772 Sym = getSymbol(GA);
773 else if (IsFunc)
774 Sym = getSymbol(FV);
775 else if (GV)
776 Sym = getSymbol(GV);
777
778 if (IsFunc) {
779 OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
780 if (FV->hasExternalLinkage())
783 // Trigger creation of function descriptor in ADA for internal
784 // functions.
785 unsigned Disp = ADATable.insert(Sym, SystemZII::MO_ADA_DIRECT_FUNC_DESC);
789 getObjFileLowering().getADASection()->getBeginSymbol(),
790 OutContext),
793 }
794 if (Sym) {
795 OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeObject);
797 }
798 return AsmPrinter::lowerConstant(CV);
799}
800
802 auto *ZOS = getTargetStreamer();
803 calculatePPA1();
804
805 // EntryPoint Marker
806 const MachineFrameInfo &MFFrame = MF->getFrameInfo();
807 bool IsUsingAlloca = MFFrame.hasVarSizedObjects();
808 uint32_t DSASize = MFFrame.getStackSize();
809 bool IsLeaf = DSASize == 0 && MFFrame.getCalleeSavedInfo().empty();
810
811 // Set Flags.
812 uint8_t Flags = 0;
813 if (IsLeaf)
814 Flags |= 0x08;
815 if (IsUsingAlloca)
816 Flags |= 0x04;
817
818 // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.
819 uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5
820 DSAAndFlags |= Flags;
821
822 // Emit entry point marker section.
823 OutStreamer->AddComment("XPLINK Routine Layout Entry");
824 OutStreamer->emitLabel(ZOS->DeferredPPA1.back().EPMarker);
825 OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
826 OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
827 OutStreamer->AddComment("Mark Type C'1'");
828 OutStreamer->emitInt8(0xF1); // Mark Type.
829 OutStreamer->AddComment("Offset to PPA1");
830 OutStreamer->emitAbsoluteSymbolDiff(ZOS->DeferredPPA1.back().PPA1,
831 ZOS->DeferredPPA1.back().EPMarker, 4);
832 if (OutStreamer->isVerboseAsm()) {
833 OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
834 OutStreamer->AddComment("Entry Flags");
835 if (Flags & 0x08)
836 OutStreamer->AddComment(" Bit 1: 1 = Leaf function");
837 else
838 OutStreamer->AddComment(" Bit 1: 0 = Non-leaf function");
839 if (Flags & 0x04)
840 OutStreamer->AddComment(" Bit 2: 1 = Uses alloca");
841 else
842 OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca");
843 }
844 OutStreamer->emitInt32(DSAAndFlags);
845
846 ZOS->emitADA(CurrentFnSym, getObjFileLowering().getADASection());
847
849
850 const Function *F = &MF->getFunction();
851 // Emit aliasing label for function entry point label.
852 for (const GlobalAlias *Alias : GOAliasMap[F]) {
853 MCSymbol *Sym = getSymbol(Alias);
854 OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
855 emitVisibility(Sym, Alias->getVisibility());
856 emitLinkage(Alias, Sym);
857 OutStreamer->emitLabel(Sym);
858 }
859}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned uint64_t
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file provides utility functions for converting between EBCDIC-1047 and UTF-8.
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
This file contains the MCSymbolGOFF class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
This file contains some functions that are useful when dealing with strings.
std::unique_ptr< MCStreamer > && Streamer
#define EMIT_COMMENT(Str)
static void determinePrologueStackUpdateSym(MachineFunction *MF, MCSymbol *&EndOfPrologSym, MCSymbol *&StackUpdateSym)
static uint32_t getProductVersion(Module &M)
static std::string getProductID(Module &M)
static time_t getTranslationTime(Module &M)
static uint32_t getProductRelease(Module &M)
static uint32_t getProductPatch(Module &M)
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
MCSymbol * getSymbol(const GlobalValue *GV) const
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
TargetMachine & TM
Target machine description.
Definition AsmPrinter.h:94
virtual void emitGlobalAlias(const Module &M, const GlobalAlias &GA)
Align emitAlignment(Align Alignment, const GlobalObject *GV=nullptr, unsigned MaxBytesToEmit=0) const
Emit an alignment directive to the specified power of two boundary.
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:109
virtual const MCExpr * lowerConstant(const Constant *CV, const Constant *BaseCV=nullptr, uint64_t Offset=0)
Lower the specified LLVM Constant to an MCExpr.
virtual void emitStartOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the start of their fi...
Definition AsmPrinter.h:619
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
virtual void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const
This emits linkage information about GVSym based on GV, if this is supported by the target.
MCSymbol * CurrentFnSym
The symbol for the current function.
Definition AsmPrinter.h:128
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:101
void emitVisibility(MCSymbol *Sym, unsigned Visibility, bool IsDefinition=true) const
This emits visibility information about symbol, if this is supported by the target.
void emitInt32(int Value) const
Emit a long directive and value.
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:106
void preprocessXXStructorList(const DataLayout &DL, const Constant *List, SmallVector< Structor, 8 > &Structors)
This method gathers an array of Structors and then sorts them out by Priority.
unsigned getPointerSize() const
Return the pointer size from the TargetMachine.
const DataLayout & getDataLayout() const
Return information about data layout.
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
This is an important base class in LLVM.
Definition Constant.h:43
const Constant * stripPointerCasts() const
Definition Constant.h:233
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
LLVM_ABI unsigned getPointerSize(unsigned AS=0) const
The pointer representation size in bytes, rounded up to a whole number of bytes.
LLVM_ABI const GlobalObject * getAliaseeObject() const
Definition Globals.cpp:730
bool hasExternalLinkage() const
LLVM_ABI const GlobalObject * getAliaseeObject() const
Definition Globals.cpp:521
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:342
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
MCInstBuilder & addReg(MCRegister Reg)
Add a new register operand.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
MCSymbol * getBeginSymbol()
Definition MCSection.h:653
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:743
StringRef getExternalName() const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
uint64_t getMaxCallFrameSize() const
Return the maximum size of a call frame that must be allocated for an outgoing function call.
int64_t getOffsetAdjustment() const
Return the correction for frame offsets.
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
bool hasStackProtectorIndex() const
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
StringRef getName() const
getName - Return the name of the corresponding LLVM function.
MCContext & getContext() const
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Representation of each machine instruction.
LLVM_ABI void setPreInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just prior to the instruction itself.
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
const GlobalValue * getGlobal() const
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
unsigned getTargetFlags() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
@ MO_GlobalAddress
Address of a global value.
@ MO_ExternalSymbol
Name of external global symbol.
iterator find(const KeyT &Key)
Definition MapVector.h:156
iterator end()
Definition MapVector.h:69
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
Wrapper class representing virtual and physical registers.
Definition Register.h:20
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
StringRef str() const
Explicit conversion to StringRef.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
void emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
SystemZAsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer)
const SystemZInstrInfo * getInstrInfo() const override
const TargetFrameLowering * getFrameLowering() const override
SystemZCallingConventionRegisters * getSpecialRegisters() const
XPLINK64 calling convention specific use registers Particular to z/OS when in 64 bit mode.
void emitGlobalAlias(const Module &M, const GlobalAlias &GA) override
bool doInitialization(Module &M) override
Set up the AsmPrinter when we are working on a new module.
SystemZXPLINKAsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer)
const MCExpr * lowerConstant(const Constant *CV, const Constant *BaseCV=nullptr, uint64_t Offset=0) override
Lower the specified LLVM Constant to an MCExpr.
void emitFunctionBodyEnd() override
Targets can override this to emit stuff after the last basic block in the function.
void emitStartOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the start of their fi...
void emitFunctionEntryLabel() override
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
void emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
void emitEndOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the end of their file...
void emitXXStructorList(const DataLayout &DL, const Constant *List, bool IsCtor) override
This method emits llvm.global_ctors or llvm.global_dtors list.
Primary interface to the complete machine description for the target machine.
MCSymbol * getSymbol(const GlobalValue *GV) const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
Twine concat(const Twine &Suffix) const
Definition Twine.h:497
static Twine utohexstr(uint64_t Val)
Definition Twine.h:385
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Language[]
Key for Kernel::Metadata::mLanguage.
LLVM_ABI std::error_code convertToEBCDIC(StringRef Source, SmallVectorImpl< char > &Result)
const unsigned GR64Regs[16]
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
Definition Metadata.h:683
UtcTime< std::chrono::seconds > toUtcTime(std::time_t T)
Convert a std::time_t to a UtcTime.
Definition Chrono.h:44
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:578
@ Length
Definition DWP.cpp:578
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
Definition STLExtras.h:1151
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
DWARFExpression::Operation Op
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
@ ZOS
z/OS MVS Exception Handling.
Definition CodeGen.h:62
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
@ MCSA_OSLinkage
symbol uses OS linkage (GOFF)
@ MCSA_IndirectSymbol
.indirect_symbol (MachO)
@ MCSA_Global
.type _foo, @gnu_unique_object
@ MCSA_Extern
.extern (XCOFF)
@ MCSA_ELF_TypeObject
.type _foo, STT_OBJECT # aka @object
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
llvm.global_ctors and llvm.global_dtors are arrays of Structor structs.
Definition AsmPrinter.h:552