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"
24#include "llvm/IR/Function.h"
25#include "llvm/IR/GlobalAlias.h"
27#include "llvm/IR/Module.h"
28#include "llvm/MC/MCExpr.h"
31#include "llvm/Support/Chrono.h"
34
35using namespace llvm;
36
41
43 SM.reset();
44
45 // In HLASM, the only way to represent aliases is to use the
46 // extra-label-at-definition strategy. This is similar to the AIX
47 // implementation with the additional caveat that all symbol attributes must
48 // be emitted before the label is emitted.
49 // Construct an aliasing list for each GlobalObject.
50 for (const auto &Alias : M.aliases()) {
51 const GlobalObject *Aliasee = Alias.getAliaseeObject();
52 if (!Aliasee)
53 OutContext.reportError(
54 {}, "Alias without a base object is not yet supported on z/OS.");
55
56 bool IsFunc = isa<Function>(Aliasee->stripPointerCasts());
57 if (IsFunc) {
58 if (Alias.hasWeakLinkage() || Alias.hasLinkOnceLinkage())
59 OutContext.reportError({},
60 "Weak alias/reference not supported on z/OS");
61
62 GOAliasMap[Aliasee].push_back(&Alias);
63 } else
64 OutContext.reportError({},
65 "Only aliases to functions is supported in GOFF.");
66 }
68}
69
70// The XPLINK ABI requires that a no-op encoding the call type is emitted after
71// each call to a subroutine. This information can be used by the called
72// function to determine its entry point, e.g. for generating a backtrace. The
73// call type is encoded as a register number in the bcr instruction. See
74// enumeration CallType for the possible values.
75void SystemZXPLINKAsmPrinter::emitCallInformation(CallType CT) {
77 MCInstBuilder(SystemZ::BCRAsm)
78 .addImm(0)
79 .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
80}
81
83SystemZXPLINKAsmPrinter::AssociatedDataAreaTable::insert(const MCSymbol *Sym,
84 unsigned SlotKind) {
85 auto Key = std::make_pair(Sym, SlotKind);
86 auto It = Displacements.find(Key);
87
88 if (It != Displacements.end())
89 return (*It).second;
90
91 // Determine length of descriptor.
93 switch (SlotKind) {
95 Length = 2 * PointerSize;
96 break;
97 default:
98 Length = PointerSize;
99 break;
100 }
101
102 uint32_t Displacement = NextDisplacement;
103 Displacements[std::make_pair(Sym, SlotKind)] = NextDisplacement;
104 NextDisplacement += Length;
105
106 return Displacement;
107}
108
109uint32_t SystemZXPLINKAsmPrinter::AssociatedDataAreaTable::insert(
110 const MachineFunction &MF, const MachineOperand &MO) {
111 MCSymbol *Sym;
113 const GlobalValue *GV = MO.getGlobal();
114 Sym = MF.getTarget().getSymbol(GV);
115 assert(Sym && "No symbol");
116 } else if (MO.getType() == MachineOperand::MO_ExternalSymbol) {
117 const char *SymName = MO.getSymbolName();
118 Sym = MF.getContext().getOrCreateSymbol(SymName);
119 assert(Sym && "No symbol");
120 } else
121 llvm_unreachable("Unexpected operand type");
122
123 unsigned ADAslotType = MO.getTargetFlags();
124 return insert(Sym, ADAslotType);
125}
126
128 SystemZMCInstLower Lower(MF->getContext(), *this);
129 MCInst LoweredMI;
130
131 switch (MI->getOpcode()) {
132 case SystemZ::CallBRASL_XPLINK64:
134 .addReg(SystemZ::R7D)
135 .addExpr(Lower.getExpr(MI->getOperand(0),
137 emitCallInformation(CallType::BRASL7);
138 return;
139
140 case SystemZ::CallBASR_XPLINK64:
142 .addReg(SystemZ::R7D)
143 .addReg(MI->getOperand(0).getReg()));
144 emitCallInformation(CallType::BASR76);
145 return;
146
147 case SystemZ::Return_XPLINK:
148 LoweredMI =
149 MCInstBuilder(SystemZ::B).addReg(SystemZ::R7D).addImm(2).addReg(0);
150 break;
151
152 case SystemZ::CondReturn_XPLINK:
153 LoweredMI = MCInstBuilder(SystemZ::BC)
154 .addImm(MI->getOperand(0).getImm())
155 .addImm(MI->getOperand(1).getImm())
156 .addReg(SystemZ::R7D)
157 .addImm(2)
158 .addReg(0);
159 break;
160
161 case SystemZ::CallBASR_STACKEXT:
163 .addReg(SystemZ::R3D)
164 .addReg(MI->getOperand(0).getReg()));
165 emitCallInformation(CallType::BASR33);
166 return;
167
168 case SystemZ::ADA_ENTRY_VALUE:
169 case SystemZ::ADA_ENTRY: {
170 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
171 const SystemZInstrInfo *TII = Subtarget.getInstrInfo();
172 uint32_t Disp = ADATable.insert(*MF, MI->getOperand(1));
173 Register TargetReg = MI->getOperand(0).getReg();
174
175 Register ADAReg = MI->getOperand(2).getReg();
176 Disp += MI->getOperand(3).getImm();
177 bool LoadAddr = MI->getOpcode() == SystemZ::ADA_ENTRY;
178
179 unsigned Op0 = LoadAddr ? SystemZ::LA : SystemZ::LG;
180 unsigned Op = TII->getOpcodeForOffset(Op0, Disp);
181
182 Register IndexReg = 0;
183 if (!Op) {
184 if (TargetReg != ADAReg) {
185 IndexReg = TargetReg;
186 // Use TargetReg to store displacement.
189 MCInstBuilder(SystemZ::LLILF).addReg(TargetReg).addImm(Disp));
190 } else
192 .addReg(TargetReg)
193 .addReg(TargetReg)
194 .addImm(Disp));
195 Disp = 0;
196 Op = Op0;
197 }
200 MCInstBuilder(Op).addReg(TargetReg).addReg(ADAReg).addImm(Disp).addReg(
201 IndexReg));
202 return;
203 }
204
205 default:
207 return;
208 }
209 EmitToStreamer(*OutStreamer, LoweredMI);
210}
211
213 const Constant *List,
214 bool IsCtor) {
215 assert(TM.getTargetTriple().isOSBinFormatGOFF() && "Only GOFF supported");
216
217 SmallVector<Structor, 8> Structors;
218 preprocessXXStructorList(DL, List, Structors);
219 if (Structors.empty())
220 return;
221
222 const Align Align = llvm::Align(4);
224 static_cast<const TargetLoweringObjectFileGOFF &>(getObjFileLowering());
225 for (Structor &S : Structors) {
226 MCSectionGOFF *Section =
227 static_cast<MCSectionGOFF *>(Obj.getStaticXtorSection(S.Priority));
228 OutStreamer->switchSection(Section);
229 if (OutStreamer->getCurrentSection() != OutStreamer->getPreviousSection())
231
232 // The priority is provided as an input to getStaticXtorSection(), and is
233 // recalculated within that function as `Prio` going to going into the
234 // PR section.
235 // This priority retrieved via the `SortKey` below is the recalculated
236 // Priority.
237 uint32_t XtorPriority = Section->getPRAttributes().SortKey;
238
239 const GlobalValue *GV = dyn_cast<GlobalValue>(S.Func->stripPointerCasts());
240 assert(GV && "C++ xxtor pointer was not a GlobalValue!");
241 MCSymbolGOFF *Symbol = static_cast<MCSymbolGOFF *>(getSymbol(GV));
242
243 // @@SQINIT entry: { unsigned prio; void (*ctor)(); void (*dtor)(); }
244
245 unsigned PointerSizeInBytes = DL.getPointerSize();
246
247 auto &Ctx = OutStreamer->getContext();
248 const MCExpr *ADAFuncRefExpr;
249 unsigned SlotKind = SystemZII::MO_ADA_DIRECT_FUNC_DESC;
250
251 MCSectionGOFF *ADASection =
252 static_cast<MCSectionGOFF *>(Obj.getADASection());
253 assert(ADASection && "ADA section must exist for GOFF targets!");
254 const MCSymbol *ADASym = ADASection->getBeginSymbol();
255 assert(ADASym && "ADA symbol should already be set!");
256
257 ADAFuncRefExpr = MCBinaryExpr::createAdd(
260 MCConstantExpr::create(ADATable.insert(Symbol, SlotKind), Ctx), Ctx);
261
262 emitInt32(XtorPriority);
263 if (IsCtor) {
264 OutStreamer->emitValue(ADAFuncRefExpr, PointerSizeInBytes);
265 OutStreamer->emitIntValue(0, PointerSizeInBytes);
266 } else {
267 OutStreamer->emitIntValue(0, PointerSizeInBytes);
268 OutStreamer->emitValue(ADAFuncRefExpr, PointerSizeInBytes);
269 }
270 }
271}
272
274 auto *ZOS = getTargetStreamer();
275 emitADASection();
276 emitIDRLSection(M);
277 // On z/OS, we need to associate an external data reference with an ED
278 // symbol, for which we use the the ED of the ADA. We also need to mark the
279 // reference as being to data, otherwise we cannot bind with code generated
280 // by XL.
281 for (auto &GO : M.global_objects()) {
282 if (auto *GV = dyn_cast<GlobalVariable>(&GO)) {
283 if (!GV->hasInitializer()) {
284 MCSymbol *Sym = getSymbol(GV);
285 ZOS->emitADA(Sym, OutContext.getObjectFileInfo()->getADASection());
286 OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeObject);
287 }
288 }
289 }
290}
291
292void SystemZXPLINKAsmPrinter::emitADASection() {
293 OutStreamer->pushSection();
294
295 const unsigned PointerSize = getDataLayout().getPointerSize();
296 OutStreamer->switchSection(getObjFileLowering().getADASection());
297
298 auto *ZOS = getTargetStreamer();
299 unsigned EmittedBytes = 0;
300 for (auto &Entry : ADATable.getTable()) {
301 const MCSymbol *Sym;
302 unsigned SlotKind;
303 std::tie(Sym, SlotKind) = Entry.first;
304 unsigned Offset = Entry.second;
305 assert(Offset == EmittedBytes && "Offset not as expected");
306 (void)EmittedBytes;
307#define EMIT_COMMENT(Str) \
308 OutStreamer->AddComment(Twine("Offset ") \
309 .concat(utostr(Offset)) \
310 .concat(" " Str " ") \
311 .concat(Sym->getName()));
312 switch (SlotKind) {
314 // Language Environment DLL logic requires function descriptors, for
315 // imported functions, that are placed in the ADA to be 8 byte aligned.
316 EMIT_COMMENT("function descriptor of");
317 OutStreamer->emitValue(
320 PointerSize);
321 OutStreamer->emitValue(
324 PointerSize);
325 EmittedBytes += PointerSize * 2;
326 break;
328 EMIT_COMMENT("pointer to data symbol");
329 OutStreamer->emitValue(
332 PointerSize);
333 EmittedBytes += PointerSize;
334 break;
337 Twine(Sym->getName()).concat("@indirect"));
338 OutStreamer->emitSymbolAttribute(Alias, MCSA_IndirectSymbol);
339 OutStreamer->emitSymbolAttribute(Alias, MCSA_ELF_TypeFunction);
340 OutStreamer->emitSymbolAttribute(Alias, MCSA_Global);
341 OutStreamer->emitSymbolAttribute(Alias, MCSA_Extern);
342 MCSymbolGOFF *GOFFSym =
343 static_cast<llvm::MCSymbolGOFF *>(const_cast<llvm::MCSymbol *>(Sym));
344 ZOS->emitExternalName(Alias, GOFFSym->getExternalName());
345 EMIT_COMMENT("pointer to function descriptor");
346 OutStreamer->emitValue(
349 PointerSize);
350 EmittedBytes += PointerSize;
351 break;
352 }
353 default:
354 llvm_unreachable("Unexpected slot kind");
355 }
356#undef EMIT_COMMENT
357 }
358 OutStreamer->popSection();
359}
360
361static std::string getProductID(Module &M) {
362 std::string ProductID;
363 if (auto *MD = M.getModuleFlag("zos_product_id"))
364 ProductID = cast<MDString>(MD)->getString().str();
365 if (ProductID.empty())
366 ProductID = "LLVM";
367 return ProductID;
368}
369
371 if (auto *VersionVal = mdconst::extract_or_null<ConstantInt>(
372 M.getModuleFlag("zos_product_major_version")))
373 return VersionVal->getZExtValue();
374 return LLVM_VERSION_MAJOR;
375}
376
378 if (auto *ReleaseVal = mdconst::extract_or_null<ConstantInt>(
379 M.getModuleFlag("zos_product_minor_version")))
380 return ReleaseVal->getZExtValue();
381 return LLVM_VERSION_MINOR;
382}
383
385 if (auto *PatchVal = mdconst::extract_or_null<ConstantInt>(
386 M.getModuleFlag("zos_product_patchlevel")))
387 return PatchVal->getZExtValue();
388 return LLVM_VERSION_PATCH;
389}
390
391static time_t getTranslationTime(Module &M) {
392 std::time_t Time = 0;
394 M.getModuleFlag("zos_translation_time"))) {
395 long SecondsSinceEpoch = Val->getSExtValue();
396 Time = static_cast<time_t>(SecondsSinceEpoch);
397 }
398 return Time;
399}
400
401void SystemZXPLINKAsmPrinter::emitIDRLSection(Module &M) {
402 OutStreamer->pushSection();
403 OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
404 constexpr unsigned IDRLDataLength = 30;
405 std::time_t Time = getTranslationTime(M);
406
407 uint32_t ProductVersion = getProductVersion(M);
408 uint32_t ProductRelease = getProductRelease(M);
409
410 std::string ProductID = getProductID(M);
411
412 SmallString<IDRLDataLength + 1> TempStr;
413 raw_svector_ostream O(TempStr);
414 O << formatv("{0,-10}{1,0-2:d}{2,0-2:d}{3:%Y%m%d%H%M%S}{4,0-2}",
415 ProductID.substr(0, 10).c_str(), ProductVersion, ProductRelease,
416 llvm::sys::toUtcTime(Time), "0");
417 SmallString<IDRLDataLength> Data;
419
420 OutStreamer->emitInt8(0); // Reserved.
421 OutStreamer->emitInt8(3); // Format.
422 OutStreamer->emitInt16(IDRLDataLength); // Length.
423 OutStreamer->emitBytes(Data.str());
424 OutStreamer->popSection();
425}
426
428 // Emit symbol for the end of function if the z/OS target streamer
429 // is used. This is needed to calculate the size of the function.
430 auto *ZOS = getTargetStreamer();
431 OutStreamer->emitLabel(ZOS->DeferredPPA1.back().FnEnd);
432}
433
434// Determine the end of the prolog and the instructions which updates the stack
435// register, and attach symbols to those instructions.
437 MCSymbol *&EndOfPrologSym,
438 MCSymbol *&StackUpdateSym) {
439 EndOfPrologSym = nullptr;
440 StackUpdateSym = nullptr;
441
442 // Scan the basic block for the FENCE instruction which marks the end
443 // of the prologue. We know
444 // the prologue is spread at most across the first 3 basic blocks. Also record
445 // the first instruction updating the stack pointer.
448 MachineInstr *EndOfPrologMI = nullptr;
449 MachineInstr *StackUpdateMI = nullptr;
450 unsigned BBCount = 1;
451
452 for (auto &MBB : *MF) {
453 for (auto &I : MBB) {
454 if (I.getOpcode() == SystemZ::FENCE)
455 EndOfPrologMI = &I;
456 else if (!StackUpdateMI) {
457 unsigned Opcode = I.getOpcode();
458 // TODO: We can instead emit a pseudo instruction in
459 // SystemZFrameLowering to represent a stack adjustment instruction, and
460 // check for that here, instead of having to check for multiple
461 // instructions.
462 if ((Opcode == SystemZ::AGHI || Opcode == SystemZ::AGFI) &&
463 I.getOperand(0).getReg() == Regs.getStackPointerRegister())
464 StackUpdateMI = &I;
465 }
466 }
467
468 // Prologue can be a max of 3 BBs if we need to call stack extension code
469 if (EndOfPrologMI || BBCount == 3)
470 break;
471
472 ++BBCount;
473 }
474
475 // Leaf functions do not have a prologue.
476 if (EndOfPrologMI == nullptr)
477 return;
478
479#ifdef EXPENSIVE_CHECKS
480 // Check that the prolog length is valid.
481 auto *TII = STI.getInstrInfo();
482 size_t Size = 0;
483
484 for (auto &MBB : *MF) {
485 bool TerminateLoop = false;
486 for (auto &I : MBB) {
487 Size += TII->getInstSizeInBytes(I);
488 if (&I == EndOfPrologMI) {
489 TerminateLoop = true;
490 break;
491 }
492 }
493 if (TerminateLoop)
494 break;
495 }
496 if (Size > 128)
498 Twine(MF->getName()).concat(": Prolog exceeds 128 bytes"));
499#endif
500
501 // Attach a temporary symbol to mark the end of the prolog.
502 EndOfPrologSym = MF->getContext().createTempSymbol("end_of_prologue");
503 EndOfPrologMI->setPostInstrSymbol(*MF, EndOfPrologSym);
504
505 if (StackUpdateMI) {
506 StackUpdateSym = MF->getContext().createTempSymbol("stack_update");
507 StackUpdateMI->setPreInstrSymbol(*MF, StackUpdateSym);
508 }
509}
510
511void SystemZXPLINKAsmPrinter::calculatePPA1() {
512 auto *ZOS = getTargetStreamer();
513 assert(ZOS->PPA2Sym != nullptr && "PPA2 Symbol not defined");
514
515 SystemZTargetzOSStreamer::PPA1Info Info;
516
517 const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
518 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
519
520 const SystemZMachineFunctionInfo *ZFI =
521 MF->getInfo<SystemZMachineFunctionInfo>();
522 const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>(
523 Subtarget.getFrameLowering());
524 const MachineFrameInfo &MFFrame = MF->getFrameInfo();
525
526 // Get saved GPR/FPR/VPR masks.
527 const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
528 uint16_t SavedGPRMask = 0;
529 uint16_t SavedFPRMask = 0;
530 uint8_t SavedVRMask = 0;
531 int64_t OffsetFPR = 0;
532 int64_t OffsetVR = 0;
533 const int64_t TopOfStack =
534 MFFrame.getOffsetAdjustment() + MFFrame.getStackSize();
535
536 // Loop over the spilled registers. The CalleeSavedInfo can't be used because
537 // it does not contain all spilled registers.
538 for (unsigned I = ZFI->getSpillGPRRegs().LowGPR,
539 E = ZFI->getSpillGPRRegs().HighGPR;
540 I && E && I <= E; ++I) {
541 unsigned V = TRI->getEncodingValue((Register)I);
542 assert(V < 16 && "GPR index out of range");
543 SavedGPRMask |= 1 << (15 - V);
544 }
545
546 for (auto &CS : CSI) {
547 unsigned Reg = CS.getReg();
548 unsigned I = TRI->getEncodingValue(Reg);
549
550 if (SystemZ::FP64BitRegClass.contains(Reg)) {
551 assert(I < 16 && "FPR index out of range");
552 SavedFPRMask |= 1 << (15 - I);
553 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
554 if (Temp < OffsetFPR)
555 OffsetFPR = Temp;
556 } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
557 assert(I >= 16 && I <= 23 && "VPR index out of range");
558 unsigned BitNum = I - 16;
559 SavedVRMask |= 1 << (7 - BitNum);
560 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
561 if (Temp < OffsetVR)
562 OffsetVR = Temp;
563 }
564 }
565
566 // Adjust the offset.
567 OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0;
568 OffsetVR += (OffsetVR < 0) ? TopOfStack : 0;
569
570 // Get alloca register.
571 uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF));
572 uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0;
573 assert(AllocaReg < 16 && "Can't have alloca register larger than 15");
574
575 MCSymbol *PersonalityRoutine = nullptr;
576 MCSymbol *GCCEH = nullptr;
577 uint64_t PersonalityADADisp = 0;
578 uint64_t GCCEHADADisp = 0;
579 if (!MF->getLandingPads().empty()) {
580 const Function *Per = dyn_cast<Function>(
581 MF->getFunction().getPersonalityFn()->stripPointerCasts());
582 PersonalityRoutine = Per ? MF->getTarget().getSymbol(Per) : nullptr;
583 if (PersonalityRoutine) {
584 GCCEH = MF->getContext().getOrCreateSymbol(
585 Twine("GCC_except_table") + Twine(MF->getFunctionNumber()));
586 PersonalityADADisp = ADATable.insert(
587 PersonalityRoutine, SystemZII::MO_ADA_INDIRECT_FUNC_DESC);
588 GCCEHADADisp = ADATable.insert(GCCEH, SystemZII::MO_ADA_DATA_SYMBOL_ADDR);
589 }
590 }
591
592 // Get the name of the function, with suffix _.
593 std::string N(MF->getFunction().hasName()
594 ? Twine(MF->getFunction().getName()).concat("_").str()
595 : "");
596
597 // Calculate the lables for the prolog size and the stack update symbol.
598 MCSymbol *EndOfPrologSym;
599 MCSymbol *StackUpdateSym;
600 determinePrologueStackUpdateSym(MF, EndOfPrologSym, StackUpdateSym);
601
602 // Save the calculated values.
603 if (MF->getFunction().hasFnAttribute("zos-ppa1-name"))
604 Info.Name =
605 MF->getFunction().getFnAttribute("zos-ppa1-name").getValueAsString();
606 else if (MF->getFunction().hasName())
607 Info.Name = MF->getFunction().getName();
608
609 Info.PPA1 = OutContext.createTempSymbol(Twine("PPA1_").concat(N), true);
610 Info.EPMarker = OutContext.createTempSymbol(Twine("EPM_").concat(N), true);
611 Info.FnEnd = OutContext.createTempSymbol(Twine(N).concat("end_"));
612 Info.Fn = CurrentFnSym;
613 Info.EndOfProlog = EndOfPrologSym;
614 Info.StackUpdate = StackUpdateSym;
615 Info.PersonalityADADisp = PersonalityADADisp;
616 Info.GCCEHADADisp = GCCEHADADisp;
617 Info.OffsetFPR = OffsetFPR;
618 Info.OffsetVR = OffsetVR;
619 Info.CallFrameSize = MFFrame.getMaxCallFrameSize();
620 Info.SizeOfFnParams = ZFI->getSizeOfFnParams();
621 Info.SavedGPRMask = SavedGPRMask;
622 Info.SavedFPRMask = SavedFPRMask;
623 Info.SavedVRMask = SavedVRMask;
624 Info.FrameReg = FrameReg;
625 Info.AllocaReg = AllocaReg;
626 Info.IsVarArg = MF->getFunction().isVarArg();
627 Info.HasStackProtector = MFFrame.hasStackProtectorIndex();
628
629 ZOS->DeferredPPA1.push_back(Info);
630}
631
636
637void SystemZXPLINKAsmPrinter::emitPPA2(Module &M) {
638 auto *ZOS = getTargetStreamer();
639 OutStreamer->pushSection();
640 OutStreamer->switchSection(getObjFileLowering().getTextSection());
641 MCContext &OutContext = OutStreamer->getContext();
642 // Make CELQSTRT symbol.
643 const char *StartSymbolName = "CELQSTRT";
644 MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);
645 OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_OSLinkage);
646 OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_Global);
647
648 // Create symbol and assign to streamer field for use in PPA1.
649 ZOS->PPA2Sym = OutContext.createTempSymbol("PPA2", false);
650 MCSymbol *PPA2Sym = ZOS->PPA2Sym;
651 MCSymbol *DateVersionSym = OutContext.createTempSymbol("DVS", false);
652
653 std::time_t Time = getTranslationTime(M);
654 SmallString<14> CompilationTimeEBCDIC, CompilationTime;
655 CompilationTime = formatv("{0:%Y%m%d%H%M%S}", llvm::sys::toUtcTime(Time));
656
657 uint32_t ProductVersion = getProductVersion(M),
658 ProductRelease = getProductRelease(M),
659 ProductPatch = getProductPatch(M);
660
661 SmallString<6> VersionEBCDIC, Version;
662 Version = formatv("{0,0-2:d}{1,0-2:d}{2,0-2:d}", ProductVersion,
663 ProductRelease, ProductPatch);
664
665 ConverterEBCDIC::convertToEBCDIC(CompilationTime, CompilationTimeEBCDIC);
667
668 enum class PPA2MemberId : uint8_t {
669 // See z/OS Language Environment Vendor Interfaces v2r5, p.23, for
670 // complete list. Only the C runtime is supported by this backend.
671 LE_C_Runtime = 3,
672 };
673 enum class PPA2MemberSubId : uint8_t {
674 // List of languages using the LE C runtime implementation.
675 C = 0x00,
676 CXX = 0x01,
677 Swift = 0x03,
678 Go = 0x60,
679 LLVMBasedLang = 0xe7,
680 };
681 // PPA2 Flags
682 enum class PPA2Flags : uint8_t {
683 CompileForBinaryFloatingPoint = 0x80,
684 CompiledWithXPLink = 0x01,
685 CompiledUnitASCII = 0x04,
686 HasServiceInfo = 0x20,
687 };
688
689 PPA2MemberSubId MemberSubId = PPA2MemberSubId::LLVMBasedLang;
690 if (auto *MD = M.getModuleFlag("zos_cu_language")) {
691 StringRef Language = cast<MDString>(MD)->getString();
692 MemberSubId = StringSwitch<PPA2MemberSubId>(Language)
693 .Case("C", PPA2MemberSubId::C)
694 .Case("C++", PPA2MemberSubId::CXX)
695 .Case("Swift", PPA2MemberSubId::Swift)
696 .Case("Go", PPA2MemberSubId::Go)
697 .Default(PPA2MemberSubId::LLVMBasedLang);
698 }
699
700 // Emit PPA2 section.
701 OutStreamer->emitLabel(PPA2Sym);
702 OutStreamer->emitInt8(static_cast<uint8_t>(PPA2MemberId::LE_C_Runtime));
703 OutStreamer->emitInt8(static_cast<uint8_t>(MemberSubId));
704 OutStreamer->emitInt8(0x22); // Member defined, c370_plist+c370_env
705 OutStreamer->emitInt8(0x04); // Control level 4 (XPLink)
706 OutStreamer->emitAbsoluteSymbolDiff(CELQSTRT, PPA2Sym, 4);
707 OutStreamer->emitInt32(0x00000000);
708 OutStreamer->emitAbsoluteSymbolDiff(DateVersionSym, PPA2Sym, 4);
709 OutStreamer->emitInt32(
710 0x00000000); // Offset to main entry point, always 0 (so says TR).
711 uint8_t Flgs = static_cast<uint8_t>(PPA2Flags::CompileForBinaryFloatingPoint);
712 Flgs |= static_cast<uint8_t>(PPA2Flags::CompiledWithXPLink);
713
714 bool IsASCII = true;
715 if (auto *MD = M.getModuleFlag("zos_le_char_mode")) {
716 const StringRef &CharMode = cast<MDString>(MD)->getString();
717 if (CharMode == "ebcdic")
718 IsASCII = false;
719 else if (CharMode != "ascii")
720 OutContext.reportError(
721 {}, "Only ascii or ebcdic are allowed for zos_le_char_mode");
722 }
723 if (IsASCII)
724 Flgs |= static_cast<uint8_t>(
725 PPA2Flags::CompiledUnitASCII); // Setting bit for ASCII char. mode.
726
727 OutStreamer->emitInt8(Flgs);
728 OutStreamer->emitInt8(0x00); // Reserved.
729 // No MD5 signature before timestamp.
730 // No FLOAT(AFP(VOLATILE)).
731 // Remaining 5 flag bits reserved.
732 OutStreamer->emitInt16(0x0000); // 16 Reserved flag bits.
733
734 // Emit date and version section.
735 OutStreamer->emitLabel(DateVersionSym);
736 OutStreamer->emitBytes(CompilationTimeEBCDIC.str());
737 OutStreamer->emitBytes(VersionEBCDIC.str());
738
739 OutStreamer->emitInt16(0x0000); // Service level string length.
740
741 // The binder requires that the offset to the PPA2 be emitted in a different,
742 // specially-named section.
743 OutStreamer->switchSection(getObjFileLowering().getPPA2ListSection());
744 // Emit 8 byte alignment.
745 // Emit pointer to PPA2 label.
746 OutStreamer->AddComment("A(PPA2-CELQSTRT)");
747 OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CELQSTRT, 8);
748 OutStreamer->popSection();
749}
750
752 const GlobalAlias &GA) {
753 if (!TM.getTargetTriple().isOSzOS())
754 return AsmPrinter::emitGlobalAlias(M, GA);
755
756 // Aliased function labels have already been emitted for z/OS
757}
758
760 const Constant *BaseCV,
761 uint64_t Offset) {
762 const GlobalAlias *GA = dyn_cast<GlobalAlias>(CV);
764 const Function *FV = dyn_cast<Function>(CV);
765 bool IsFunc = !GV && (FV || (GA && isa<Function>(GA->getAliaseeObject())));
766
767 MCSymbol *Sym = NULL;
768
769 if (GA)
770 Sym = getSymbol(GA);
771 else if (IsFunc)
772 Sym = getSymbol(FV);
773 else if (GV)
774 Sym = getSymbol(GV);
775
776 if (IsFunc) {
777 OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
778 if (FV->hasExternalLinkage())
781 // Trigger creation of function descriptor in ADA for internal
782 // functions.
783 unsigned Disp = ADATable.insert(Sym, SystemZII::MO_ADA_DIRECT_FUNC_DESC);
787 getObjFileLowering().getADASection()->getBeginSymbol(),
788 OutContext),
791 }
792 if (Sym) {
793 OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeObject);
795 }
796 return AsmPrinter::lowerConstant(CV);
797}
798
800 auto *ZOS = getTargetStreamer();
801 calculatePPA1();
802
803 // EntryPoint Marker
804 const MachineFrameInfo &MFFrame = MF->getFrameInfo();
805 bool IsUsingAlloca = MFFrame.hasVarSizedObjects();
806 uint32_t DSASize = MFFrame.getStackSize();
807 bool IsLeaf = DSASize == 0 && MFFrame.getCalleeSavedInfo().empty();
808
809 // Set Flags.
810 uint8_t Flags = 0;
811 if (IsLeaf)
812 Flags |= 0x08;
813 if (IsUsingAlloca)
814 Flags |= 0x04;
815
816 // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.
817 uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5
818 DSAAndFlags |= Flags;
819
820 // Emit entry point marker section.
821 OutStreamer->AddComment("XPLINK Routine Layout Entry");
822 OutStreamer->emitLabel(ZOS->DeferredPPA1.back().EPMarker);
823 OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
824 OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
825 OutStreamer->AddComment("Mark Type C'1'");
826 OutStreamer->emitInt8(0xF1); // Mark Type.
827 OutStreamer->AddComment("Offset to PPA1");
828 OutStreamer->emitAbsoluteSymbolDiff(ZOS->DeferredPPA1.back().PPA1,
829 ZOS->DeferredPPA1.back().EPMarker, 4);
830 if (OutStreamer->isVerboseAsm()) {
831 OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
832 OutStreamer->AddComment("Entry Flags");
833 if (Flags & 0x08)
834 OutStreamer->AddComment(" Bit 1: 1 = Leaf function");
835 else
836 OutStreamer->AddComment(" Bit 1: 0 = Non-leaf function");
837 if (Flags & 0x04)
838 OutStreamer->AddComment(" Bit 2: 1 = Uses alloca");
839 else
840 OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca");
841 }
842 OutStreamer->emitInt32(DSAAndFlags);
843
844 ZOS->emitADA(CurrentFnSym, getObjFileLowering().getADASection());
845
847
848 const Function *F = &MF->getFunction();
849 // Emit aliasing label for function entry point label.
850 for (const GlobalAlias *Alias : GOAliasMap[F]) {
851 MCSymbol *Sym = getSymbol(Alias);
852 OutStreamer->emitSymbolAttribute(Sym, MCSA_ELF_TypeFunction);
853 emitVisibility(Sym, Alias->getVisibility());
854 emitLinkage(Alias, Sym);
855 OutStreamer->emitLabel(Sym);
856 }
857}
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
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.
const GlobalValue * getGlobal() const
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:68
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.
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:577
@ Length
Definition DWP.cpp:577
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