LLVM 22.0.0git
SystemZAsmPrinter.cpp
Go to the documentation of this file.
1//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Streams SystemZ assembly language and associated data, in the form of
10// MCInsts and MCExprs respectively.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SystemZAsmPrinter.h"
20#include "SystemZMCInstLower.h"
27#include "llvm/IR/Mangler.h"
28#include "llvm/IR/Module.h"
30#include "llvm/MC/MCExpr.h"
33#include "llvm/MC/MCStreamer.h"
35#include "llvm/Support/Chrono.h"
39
40using namespace llvm;
41
42// Return an RI instruction like MI with opcode Opcode, but with the
43// GR64 register operands turned into GR32s.
44static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
45 if (MI->isCompare())
46 return MCInstBuilder(Opcode)
47 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
48 .addImm(MI->getOperand(1).getImm());
49 else
50 return MCInstBuilder(Opcode)
51 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
52 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))
53 .addImm(MI->getOperand(2).getImm());
54}
55
56// Return an RI instruction like MI with opcode Opcode, but with the
57// GR64 register operands turned into GRH32s.
58static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {
59 if (MI->isCompare())
60 return MCInstBuilder(Opcode)
61 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
62 .addImm(MI->getOperand(1).getImm());
63 else
64 return MCInstBuilder(Opcode)
65 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
66 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg()))
67 .addImm(MI->getOperand(2).getImm());
68}
69
70// Return an RI instruction like MI with opcode Opcode, but with the
71// R2 register turned into a GR64.
72static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
73 return MCInstBuilder(Opcode)
74 .addReg(MI->getOperand(0).getReg())
75 .addReg(MI->getOperand(1).getReg())
76 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))
77 .addImm(MI->getOperand(3).getImm())
78 .addImm(MI->getOperand(4).getImm())
79 .addImm(MI->getOperand(5).getImm());
80}
81
82static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
83 StringRef Name = "__tls_get_offset";
84 return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
85 SystemZ::S_PLT, Context);
86}
87
89 StringRef Name = "_GLOBAL_OFFSET_TABLE_";
90 return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
91 Context);
92}
93
94// MI is an instruction that accepts an optional alignment hint,
95// and which was already lowered to LoweredMI. If the alignment
96// of the original memory operand is known, update LoweredMI to
97// an instruction with the corresponding hint set.
98static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI,
99 unsigned Opcode) {
100 if (MI->memoperands_empty())
101 return;
102
103 Align Alignment = Align(16);
104 for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(),
105 EE = MI->memoperands_end(); MMOI != EE; ++MMOI)
106 if ((*MMOI)->getAlign() < Alignment)
107 Alignment = (*MMOI)->getAlign();
108
109 unsigned AlignmentHint = 0;
110 if (Alignment >= Align(16))
111 AlignmentHint = 4;
112 else if (Alignment >= Align(8))
113 AlignmentHint = 3;
114 if (AlignmentHint == 0)
115 return;
116
117 LoweredMI.setOpcode(Opcode);
118 LoweredMI.addOperand(MCOperand::createImm(AlignmentHint));
119}
120
121// MI loads the high part of a vector from memory. Return an instruction
122// that uses replicating vector load Opcode to do the same thing.
123static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {
124 return MCInstBuilder(Opcode)
125 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
126 .addReg(MI->getOperand(1).getReg())
127 .addImm(MI->getOperand(2).getImm())
128 .addReg(MI->getOperand(3).getReg());
129}
130
131// MI stores the high part of a vector to memory. Return an instruction
132// that uses elemental vector store Opcode to do the same thing.
133static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
134 return MCInstBuilder(Opcode)
135 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
136 .addReg(MI->getOperand(1).getReg())
137 .addImm(MI->getOperand(2).getImm())
138 .addReg(MI->getOperand(3).getReg())
139 .addImm(0);
140}
141
142// MI extracts the first element of the source vector.
143static MCInst lowerVecEltExtraction(const MachineInstr *MI, unsigned Opcode) {
144 return MCInstBuilder(Opcode)
145 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg()))
146 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()))
147 .addReg(0)
148 .addImm(0);
149}
150
151// MI inserts value into the first element of the destination vector.
152static MCInst lowerVecEltInsertion(const MachineInstr *MI, unsigned Opcode) {
153 return MCInstBuilder(Opcode)
154 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
155 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
156 .addReg(MI->getOperand(1).getReg())
157 .addReg(0)
158 .addImm(0);
159}
160
161// The XPLINK ABI requires that a no-op encoding the call type is emitted after
162// each call to a subroutine. This information can be used by the called
163// function to determine its entry point, e.g. for generating a backtrace. The
164// call type is encoded as a register number in the bcr instruction. See
165// enumeration CallType for the possible values.
166void SystemZAsmPrinter::emitCallInformation(CallType CT) {
168 MCInstBuilder(SystemZ::BCRAsm)
169 .addImm(0)
170 .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
171}
172
173uint32_t SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MCSymbol *Sym,
174 unsigned SlotKind) {
175 auto Key = std::make_pair(Sym, SlotKind);
176 auto It = Displacements.find(Key);
177
178 if (It != Displacements.end())
179 return (*It).second;
180
181 // Determine length of descriptor.
182 uint32_t Length;
183 switch (SlotKind) {
185 Length = 2 * PointerSize;
186 break;
187 default:
188 Length = PointerSize;
189 break;
190 }
191
192 uint32_t Displacement = NextDisplacement;
193 Displacements[std::make_pair(Sym, SlotKind)] = NextDisplacement;
194 NextDisplacement += Length;
195
196 return Displacement;
197}
198
199uint32_t
200SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MachineOperand MO) {
201 MCSymbol *Sym;
203 const GlobalValue *GV = MO.getGlobal();
204 Sym = MO.getParent()->getMF()->getTarget().getSymbol(GV);
205 assert(Sym && "No symbol");
206 } else if (MO.getType() == MachineOperand::MO_ExternalSymbol) {
207 const char *SymName = MO.getSymbolName();
208 Sym = MO.getParent()->getMF()->getContext().getOrCreateSymbol(SymName);
209 assert(Sym && "No symbol");
210 } else
211 llvm_unreachable("Unexpected operand type");
212
213 unsigned ADAslotType = MO.getTargetFlags();
214 return insert(Sym, ADAslotType);
215}
216
218 SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(),
219 getSubtargetInfo().getFeatureBits());
220
221 SystemZMCInstLower Lower(MF->getContext(), *this);
222 MCInst LoweredMI;
223 switch (MI->getOpcode()) {
224 case SystemZ::Return:
225 LoweredMI = MCInstBuilder(SystemZ::BR)
226 .addReg(SystemZ::R14D);
227 break;
228
229 case SystemZ::Return_XPLINK:
230 LoweredMI = MCInstBuilder(SystemZ::B)
231 .addReg(SystemZ::R7D)
232 .addImm(2)
233 .addReg(0);
234 break;
235
236 case SystemZ::CondReturn:
237 LoweredMI = MCInstBuilder(SystemZ::BCR)
238 .addImm(MI->getOperand(0).getImm())
239 .addImm(MI->getOperand(1).getImm())
240 .addReg(SystemZ::R14D);
241 break;
242
243 case SystemZ::CondReturn_XPLINK:
244 LoweredMI = MCInstBuilder(SystemZ::BC)
245 .addImm(MI->getOperand(0).getImm())
246 .addImm(MI->getOperand(1).getImm())
247 .addReg(SystemZ::R7D)
248 .addImm(2)
249 .addReg(0);
250 break;
251
252 case SystemZ::CRBReturn:
253 LoweredMI = MCInstBuilder(SystemZ::CRB)
254 .addReg(MI->getOperand(0).getReg())
255 .addReg(MI->getOperand(1).getReg())
256 .addImm(MI->getOperand(2).getImm())
257 .addReg(SystemZ::R14D)
258 .addImm(0);
259 break;
260
261 case SystemZ::CGRBReturn:
262 LoweredMI = MCInstBuilder(SystemZ::CGRB)
263 .addReg(MI->getOperand(0).getReg())
264 .addReg(MI->getOperand(1).getReg())
265 .addImm(MI->getOperand(2).getImm())
266 .addReg(SystemZ::R14D)
267 .addImm(0);
268 break;
269
270 case SystemZ::CIBReturn:
271 LoweredMI = MCInstBuilder(SystemZ::CIB)
272 .addReg(MI->getOperand(0).getReg())
273 .addImm(MI->getOperand(1).getImm())
274 .addImm(MI->getOperand(2).getImm())
275 .addReg(SystemZ::R14D)
276 .addImm(0);
277 break;
278
279 case SystemZ::CGIBReturn:
280 LoweredMI = MCInstBuilder(SystemZ::CGIB)
281 .addReg(MI->getOperand(0).getReg())
282 .addImm(MI->getOperand(1).getImm())
283 .addImm(MI->getOperand(2).getImm())
284 .addReg(SystemZ::R14D)
285 .addImm(0);
286 break;
287
288 case SystemZ::CLRBReturn:
289 LoweredMI = MCInstBuilder(SystemZ::CLRB)
290 .addReg(MI->getOperand(0).getReg())
291 .addReg(MI->getOperand(1).getReg())
292 .addImm(MI->getOperand(2).getImm())
293 .addReg(SystemZ::R14D)
294 .addImm(0);
295 break;
296
297 case SystemZ::CLGRBReturn:
298 LoweredMI = MCInstBuilder(SystemZ::CLGRB)
299 .addReg(MI->getOperand(0).getReg())
300 .addReg(MI->getOperand(1).getReg())
301 .addImm(MI->getOperand(2).getImm())
302 .addReg(SystemZ::R14D)
303 .addImm(0);
304 break;
305
306 case SystemZ::CLIBReturn:
307 LoweredMI = MCInstBuilder(SystemZ::CLIB)
308 .addReg(MI->getOperand(0).getReg())
309 .addImm(MI->getOperand(1).getImm())
310 .addImm(MI->getOperand(2).getImm())
311 .addReg(SystemZ::R14D)
312 .addImm(0);
313 break;
314
315 case SystemZ::CLGIBReturn:
316 LoweredMI = MCInstBuilder(SystemZ::CLGIB)
317 .addReg(MI->getOperand(0).getReg())
318 .addImm(MI->getOperand(1).getImm())
319 .addImm(MI->getOperand(2).getImm())
320 .addReg(SystemZ::R14D)
321 .addImm(0);
322 break;
323
324 case SystemZ::CallBRASL_XPLINK64:
326 .addReg(SystemZ::R7D)
327 .addExpr(Lower.getExpr(MI->getOperand(0),
329 emitCallInformation(CallType::BRASL7);
330 return;
331
332 case SystemZ::CallBASR_XPLINK64:
334 .addReg(SystemZ::R7D)
335 .addReg(MI->getOperand(0).getReg()));
336 emitCallInformation(CallType::BASR76);
337 return;
338
339 case SystemZ::CallBASR_STACKEXT:
341 .addReg(SystemZ::R3D)
342 .addReg(MI->getOperand(0).getReg()));
343 emitCallInformation(CallType::BASR33);
344 return;
345
346 case SystemZ::ADA_ENTRY_VALUE:
347 case SystemZ::ADA_ENTRY: {
348 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
349 const SystemZInstrInfo *TII = Subtarget.getInstrInfo();
350 uint32_t Disp = ADATable.insert(MI->getOperand(1));
351 Register TargetReg = MI->getOperand(0).getReg();
352
353 Register ADAReg = MI->getOperand(2).getReg();
354 Disp += MI->getOperand(3).getImm();
355 bool LoadAddr = MI->getOpcode() == SystemZ::ADA_ENTRY;
356
357 unsigned Op0 = LoadAddr ? SystemZ::LA : SystemZ::LG;
358 unsigned Op = TII->getOpcodeForOffset(Op0, Disp);
359
360 Register IndexReg = 0;
361 if (!Op) {
362 if (TargetReg != ADAReg) {
363 IndexReg = TargetReg;
364 // Use TargetReg to store displacement.
367 MCInstBuilder(SystemZ::LLILF).addReg(TargetReg).addImm(Disp));
368 } else
370 .addReg(TargetReg)
371 .addReg(TargetReg)
372 .addImm(Disp));
373 Disp = 0;
374 Op = Op0;
375 }
377 .addReg(TargetReg)
378 .addReg(ADAReg)
379 .addImm(Disp)
380 .addReg(IndexReg));
381
382 return;
383 }
384 case SystemZ::CallBRASL:
385 LoweredMI = MCInstBuilder(SystemZ::BRASL)
386 .addReg(SystemZ::R14D)
387 .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_PLT));
388 break;
389
390 case SystemZ::CallBASR:
391 LoweredMI = MCInstBuilder(SystemZ::BASR)
392 .addReg(SystemZ::R14D)
393 .addReg(MI->getOperand(0).getReg());
394 break;
395
396 case SystemZ::CallJG:
397 LoweredMI = MCInstBuilder(SystemZ::JG)
398 .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_PLT));
399 break;
400
401 case SystemZ::CallBRCL:
402 LoweredMI = MCInstBuilder(SystemZ::BRCL)
403 .addImm(MI->getOperand(0).getImm())
404 .addImm(MI->getOperand(1).getImm())
405 .addExpr(Lower.getExpr(MI->getOperand(2), SystemZ::S_PLT));
406 break;
407
408 case SystemZ::CallBR:
409 LoweredMI = MCInstBuilder(SystemZ::BR)
410 .addReg(MI->getOperand(0).getReg());
411 break;
412
413 case SystemZ::CallBCR:
414 LoweredMI = MCInstBuilder(SystemZ::BCR)
415 .addImm(MI->getOperand(0).getImm())
416 .addImm(MI->getOperand(1).getImm())
417 .addReg(MI->getOperand(2).getReg());
418 break;
419
420 case SystemZ::CRBCall:
421 LoweredMI = MCInstBuilder(SystemZ::CRB)
422 .addReg(MI->getOperand(0).getReg())
423 .addReg(MI->getOperand(1).getReg())
424 .addImm(MI->getOperand(2).getImm())
425 .addReg(MI->getOperand(3).getReg())
426 .addImm(0);
427 break;
428
429 case SystemZ::CGRBCall:
430 LoweredMI = MCInstBuilder(SystemZ::CGRB)
431 .addReg(MI->getOperand(0).getReg())
432 .addReg(MI->getOperand(1).getReg())
433 .addImm(MI->getOperand(2).getImm())
434 .addReg(MI->getOperand(3).getReg())
435 .addImm(0);
436 break;
437
438 case SystemZ::CIBCall:
439 LoweredMI = MCInstBuilder(SystemZ::CIB)
440 .addReg(MI->getOperand(0).getReg())
441 .addImm(MI->getOperand(1).getImm())
442 .addImm(MI->getOperand(2).getImm())
443 .addReg(MI->getOperand(3).getReg())
444 .addImm(0);
445 break;
446
447 case SystemZ::CGIBCall:
448 LoweredMI = MCInstBuilder(SystemZ::CGIB)
449 .addReg(MI->getOperand(0).getReg())
450 .addImm(MI->getOperand(1).getImm())
451 .addImm(MI->getOperand(2).getImm())
452 .addReg(MI->getOperand(3).getReg())
453 .addImm(0);
454 break;
455
456 case SystemZ::CLRBCall:
457 LoweredMI = MCInstBuilder(SystemZ::CLRB)
458 .addReg(MI->getOperand(0).getReg())
459 .addReg(MI->getOperand(1).getReg())
460 .addImm(MI->getOperand(2).getImm())
461 .addReg(MI->getOperand(3).getReg())
462 .addImm(0);
463 break;
464
465 case SystemZ::CLGRBCall:
466 LoweredMI = MCInstBuilder(SystemZ::CLGRB)
467 .addReg(MI->getOperand(0).getReg())
468 .addReg(MI->getOperand(1).getReg())
469 .addImm(MI->getOperand(2).getImm())
470 .addReg(MI->getOperand(3).getReg())
471 .addImm(0);
472 break;
473
474 case SystemZ::CLIBCall:
475 LoweredMI = MCInstBuilder(SystemZ::CLIB)
476 .addReg(MI->getOperand(0).getReg())
477 .addImm(MI->getOperand(1).getImm())
478 .addImm(MI->getOperand(2).getImm())
479 .addReg(MI->getOperand(3).getReg())
480 .addImm(0);
481 break;
482
483 case SystemZ::CLGIBCall:
484 LoweredMI = MCInstBuilder(SystemZ::CLGIB)
485 .addReg(MI->getOperand(0).getReg())
486 .addImm(MI->getOperand(1).getImm())
487 .addImm(MI->getOperand(2).getImm())
488 .addReg(MI->getOperand(3).getReg())
489 .addImm(0);
490 break;
491
492 case SystemZ::TLS_GDCALL:
493 LoweredMI =
494 MCInstBuilder(SystemZ::BRASL)
495 .addReg(SystemZ::R14D)
496 .addExpr(getTLSGetOffset(MF->getContext()))
497 .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_TLSGD));
498 break;
499
500 case SystemZ::TLS_LDCALL:
501 LoweredMI =
502 MCInstBuilder(SystemZ::BRASL)
503 .addReg(SystemZ::R14D)
504 .addExpr(getTLSGetOffset(MF->getContext()))
505 .addExpr(Lower.getExpr(MI->getOperand(0), SystemZ::S_TLSLDM));
506 break;
507
508 case SystemZ::GOT:
509 LoweredMI = MCInstBuilder(SystemZ::LARL)
510 .addReg(MI->getOperand(0).getReg())
511 .addExpr(getGlobalOffsetTable(MF->getContext()));
512 break;
513
514 case SystemZ::IILF64:
515 LoweredMI = MCInstBuilder(SystemZ::IILF)
516 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
517 .addImm(MI->getOperand(2).getImm());
518 break;
519
520 case SystemZ::IIHF64:
521 LoweredMI = MCInstBuilder(SystemZ::IIHF)
522 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
523 .addImm(MI->getOperand(2).getImm());
524 break;
525
526 case SystemZ::RISBHH:
527 case SystemZ::RISBHL:
528 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
529 break;
530
531 case SystemZ::RISBLH:
532 case SystemZ::RISBLL:
533 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
534 break;
535
536 case SystemZ::VLVGP32:
537 LoweredMI = MCInstBuilder(SystemZ::VLVGP)
538 .addReg(MI->getOperand(0).getReg())
539 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg()))
540 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()));
541 break;
542
543 case SystemZ::VLR32:
544 case SystemZ::VLR64:
545 LoweredMI = MCInstBuilder(SystemZ::VLR)
546 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
547 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()));
548 break;
549
550 case SystemZ::VL:
551 Lower.lower(MI, LoweredMI);
552 lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign);
553 break;
554
555 case SystemZ::VST:
556 Lower.lower(MI, LoweredMI);
557 lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign);
558 break;
559
560 case SystemZ::VLM:
561 Lower.lower(MI, LoweredMI);
562 lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign);
563 break;
564
565 case SystemZ::VSTM:
566 Lower.lower(MI, LoweredMI);
567 lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign);
568 break;
569
570 case SystemZ::VL16:
571 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPH);
572 break;
573
574 case SystemZ::VL32:
575 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF);
576 break;
577
578 case SystemZ::VL64:
579 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG);
580 break;
581
582 case SystemZ::VST16:
583 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEH);
584 break;
585
586 case SystemZ::VST32:
587 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF);
588 break;
589
590 case SystemZ::VST64:
591 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG);
592 break;
593
594 case SystemZ::LFER:
595 LoweredMI = lowerVecEltExtraction(MI, SystemZ::VLGVF);
596 break;
597
598 case SystemZ::LFER_16:
599 LoweredMI = lowerVecEltExtraction(MI, SystemZ::VLGVH);
600 break;
601
602 case SystemZ::LEFR:
603 LoweredMI = lowerVecEltInsertion(MI, SystemZ::VLVGF);
604 break;
605
606 case SystemZ::LEFR_16:
607 LoweredMI = lowerVecEltInsertion(MI, SystemZ::VLVGH);
608 break;
609
610#define LOWER_LOW(NAME) \
611 case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
612
613 LOWER_LOW(IILL);
614 LOWER_LOW(IILH);
615 LOWER_LOW(TMLL);
616 LOWER_LOW(TMLH);
617 LOWER_LOW(NILL);
618 LOWER_LOW(NILH);
619 LOWER_LOW(NILF);
620 LOWER_LOW(OILL);
621 LOWER_LOW(OILH);
622 LOWER_LOW(OILF);
623 LOWER_LOW(XILF);
624
625#undef LOWER_LOW
626
627#define LOWER_HIGH(NAME) \
628 case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
629
630 LOWER_HIGH(IIHL);
631 LOWER_HIGH(IIHH);
632 LOWER_HIGH(TMHL);
633 LOWER_HIGH(TMHH);
634 LOWER_HIGH(NIHL);
635 LOWER_HIGH(NIHH);
636 LOWER_HIGH(NIHF);
637 LOWER_HIGH(OIHL);
638 LOWER_HIGH(OIHH);
639 LOWER_HIGH(OIHF);
640 LOWER_HIGH(XIHF);
641
642#undef LOWER_HIGH
643
644 case SystemZ::Serialize:
645 if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
646 LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
647 .addImm(14).addReg(SystemZ::R0D);
648 else
649 LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
650 .addImm(15).addReg(SystemZ::R0D);
651 break;
652
653 // We want to emit "j .+2" for traps, jumping to the relative immediate field
654 // of the jump instruction, which is an illegal instruction. We cannot emit a
655 // "." symbol, so create and emit a temp label before the instruction and use
656 // that instead.
657 case SystemZ::Trap: {
658 MCSymbol *DotSym = OutContext.createTempSymbol();
659 OutStreamer->emitLabel(DotSym);
660
662 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
663 LoweredMI = MCInstBuilder(SystemZ::J)
664 .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
665 }
666 break;
667
668 // Conditional traps will create a branch on condition instruction that jumps
669 // to the relative immediate field of the jump instruction. (eg. "jo .+2")
670 case SystemZ::CondTrap: {
671 MCSymbol *DotSym = OutContext.createTempSymbol();
672 OutStreamer->emitLabel(DotSym);
673
675 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
676 LoweredMI = MCInstBuilder(SystemZ::BRC)
677 .addImm(MI->getOperand(0).getImm())
678 .addImm(MI->getOperand(1).getImm())
679 .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
680 }
681 break;
682
683 case TargetOpcode::FENTRY_CALL:
684 LowerFENTRY_CALL(*MI, Lower);
685 return;
686
687 case TargetOpcode::STACKMAP:
688 LowerSTACKMAP(*MI);
689 return;
690
691 case TargetOpcode::PATCHPOINT:
692 LowerPATCHPOINT(*MI, Lower);
693 return;
694
695 case TargetOpcode::PATCHABLE_FUNCTION_ENTER:
696 LowerPATCHABLE_FUNCTION_ENTER(*MI, Lower);
697 return;
698
699 case TargetOpcode::PATCHABLE_RET:
700 LowerPATCHABLE_RET(*MI, Lower);
701 return;
702
703 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
704 llvm_unreachable("PATCHABLE_FUNCTION_EXIT should never be emitted");
705
706 case TargetOpcode::PATCHABLE_TAIL_CALL:
707 // TODO: Define a trampoline `__xray_FunctionTailExit` and differentiate a
708 // normal function exit from a tail exit.
709 llvm_unreachable("Tail call is handled in the normal case. See comments "
710 "around this assert.");
711
712 case SystemZ::EXRL_Pseudo: {
713 unsigned TargetInsOpc = MI->getOperand(0).getImm();
714 Register LenMinus1Reg = MI->getOperand(1).getReg();
715 Register DestReg = MI->getOperand(2).getReg();
716 int64_t DestDisp = MI->getOperand(3).getImm();
717 Register SrcReg = MI->getOperand(4).getReg();
718 int64_t SrcDisp = MI->getOperand(5).getImm();
719
720 SystemZTargetStreamer *TS = getTargetStreamer();
721 MCInst ET = MCInstBuilder(TargetInsOpc)
722 .addReg(DestReg)
723 .addImm(DestDisp)
724 .addImm(1)
725 .addReg(SrcReg)
726 .addImm(SrcDisp);
727 SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
728 auto [It, Inserted] = TS->EXRLTargets2Sym.try_emplace(ET_STI);
729 if (Inserted)
730 It->second = OutContext.createTempSymbol();
731 MCSymbol *DotSym = It->second;
735 MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));
736 return;
737 }
738
739 // EH_SjLj_Setup is a dummy terminator instruction of size 0.
740 // It is used to handle the clobber register for builtin setjmp.
741 case SystemZ::EH_SjLj_Setup:
742 return;
743
744 default:
745 Lower.lower(MI, LoweredMI);
746 break;
747 }
748 EmitToStreamer(*OutStreamer, LoweredMI);
749}
750
751// Emit the largest nop instruction smaller than or equal to NumBytes
752// bytes. Return the size of nop emitted.
754 unsigned NumBytes, const MCSubtargetInfo &STI) {
755 if (NumBytes < 2) {
756 llvm_unreachable("Zero nops?");
757 return 0;
758 }
759 else if (NumBytes < 4) {
760 OutStreamer.emitInstruction(
761 MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
762 return 2;
763 }
764 else if (NumBytes < 6) {
765 OutStreamer.emitInstruction(
766 MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
767 STI);
768 return 4;
769 }
770 else {
773 OutStreamer.emitLabel(DotSym);
774 OutStreamer.emitInstruction(
775 MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
776 return 6;
777 }
778}
779
780void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
781 SystemZMCInstLower &Lower) {
782 MCContext &Ctx = MF->getContext();
783 if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
784 MCSymbol *DotSym = OutContext.createTempSymbol();
785 OutStreamer->pushSection();
786 OutStreamer->switchSection(
787 Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
788 OutStreamer->emitSymbolValue(DotSym, 8);
789 OutStreamer->popSection();
790 OutStreamer->emitLabel(DotSym);
791 }
792
793 if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
795 return;
796 }
797
798 MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
799 const MCSymbolRefExpr *Op =
801 OutStreamer->emitInstruction(
802 MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
804}
805
806void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
807 auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo();
808
809 unsigned NumNOPBytes = MI.getOperand(1).getImm();
810
811 auto &Ctx = OutStreamer->getContext();
812 MCSymbol *MILabel = Ctx.createTempSymbol();
813 OutStreamer->emitLabel(MILabel);
814
815 SM.recordStackMap(*MILabel, MI);
816 assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
817
818 // Scan ahead to trim the shadow.
819 unsigned ShadowBytes = 0;
820 const MachineBasicBlock &MBB = *MI.getParent();
822 ++MII;
823 while (ShadowBytes < NumNOPBytes) {
824 if (MII == MBB.end() ||
825 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
826 MII->getOpcode() == TargetOpcode::STACKMAP)
827 break;
828 ShadowBytes += TII->getInstSizeInBytes(*MII);
829 if (MII->isCall())
830 break;
831 ++MII;
832 }
833
834 // Emit nops.
835 while (ShadowBytes < NumNOPBytes)
836 ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
838}
839
840// Lower a patchpoint of the form:
841// [<def>], <id>, <numBytes>, <target>, <numArgs>
842void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
843 SystemZMCInstLower &Lower) {
844 auto &Ctx = OutStreamer->getContext();
845 MCSymbol *MILabel = Ctx.createTempSymbol();
846 OutStreamer->emitLabel(MILabel);
847
848 SM.recordPatchPoint(*MILabel, MI);
849 PatchPointOpers Opers(&MI);
850
851 unsigned EncodedBytes = 0;
852 const MachineOperand &CalleeMO = Opers.getCallTarget();
853
854 if (CalleeMO.isImm()) {
855 uint64_t CallTarget = CalleeMO.getImm();
856 if (CallTarget) {
857 unsigned ScratchIdx = -1;
858 unsigned ScratchReg = 0;
859 do {
860 ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
861 ScratchReg = MI.getOperand(ScratchIdx).getReg();
862 } while (ScratchReg == SystemZ::R0D);
863
864 // Materialize the call target address
865 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
866 .addReg(ScratchReg)
867 .addImm(CallTarget & 0xFFFFFFFF));
868 EncodedBytes += 6;
869 if (CallTarget >> 32) {
870 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
871 .addReg(ScratchReg)
872 .addImm(CallTarget >> 32));
873 EncodedBytes += 6;
874 }
875
876 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
877 .addReg(SystemZ::R14D)
878 .addReg(ScratchReg));
879 EncodedBytes += 2;
880 }
881 } else if (CalleeMO.isGlobal()) {
882 const MCExpr *Expr = Lower.getExpr(CalleeMO, SystemZ::S_PLT);
883 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
884 .addReg(SystemZ::R14D)
885 .addExpr(Expr));
886 EncodedBytes += 6;
887 }
888
889 // Emit padding.
890 unsigned NumBytes = Opers.getNumPatchBytes();
891 assert(NumBytes >= EncodedBytes &&
892 "Patchpoint can't request size less than the length of a call.");
893 assert((NumBytes - EncodedBytes) % 2 == 0 &&
894 "Invalid number of NOP bytes requested!");
895 while (EncodedBytes < NumBytes)
896 EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
898}
899
900void SystemZAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
901 const MachineInstr &MI, SystemZMCInstLower &Lower) {
902 // .begin:
903 // j .end # -> stmg %r2, %r15, 16(%r15)
904 // nop
905 // llilf %2, FuncID
906 // brasl %r14, __xray_FunctionEntry@GOT
907 // .end:
908 //
909 // Update compiler-rt/lib/xray/xray_s390x.cpp accordingly when number
910 // of instructions change.
911 bool HasVectorFeature =
912 TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureVector) &&
913 !TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureSoftFloat);
914 MCSymbol *FuncEntry = OutContext.getOrCreateSymbol(
915 HasVectorFeature ? "__xray_FunctionEntryVec" : "__xray_FunctionEntry");
916 MCSymbol *BeginOfSled = OutContext.createTempSymbol("xray_sled_", true);
917 MCSymbol *EndOfSled = OutContext.createTempSymbol();
918 OutStreamer->emitLabel(BeginOfSled);
920 MCInstBuilder(SystemZ::J)
921 .addExpr(MCSymbolRefExpr::create(EndOfSled, OutContext)));
924 MCInstBuilder(SystemZ::LLILF).addReg(SystemZ::R2D).addImm(0));
925 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
926 .addReg(SystemZ::R14D)
928 FuncEntry, SystemZ::S_PLT, OutContext)));
929 OutStreamer->emitLabel(EndOfSled);
930 recordSled(BeginOfSled, MI, SledKind::FUNCTION_ENTER, 2);
931}
932
933void SystemZAsmPrinter::LowerPATCHABLE_RET(const MachineInstr &MI,
934 SystemZMCInstLower &Lower) {
935 unsigned OpCode = MI.getOperand(0).getImm();
936 MCSymbol *FallthroughLabel = nullptr;
937 if (OpCode == SystemZ::CondReturn) {
938 FallthroughLabel = OutContext.createTempSymbol();
939 int64_t Cond0 = MI.getOperand(1).getImm();
940 int64_t Cond1 = MI.getOperand(2).getImm();
941 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRC)
942 .addImm(Cond0)
943 .addImm(Cond1 ^ Cond0)
945 FallthroughLabel, OutContext)));
946 }
947 // .begin:
948 // br %r14 # -> stmg %r2, %r15, 24(%r15)
949 // nop
950 // nop
951 // llilf %2,FuncID
952 // j __xray_FunctionExit@GOT
953 //
954 // Update compiler-rt/lib/xray/xray_s390x.cpp accordingly when number
955 // of instructions change.
956 bool HasVectorFeature =
957 TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureVector) &&
958 !TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureSoftFloat);
959 MCSymbol *FuncExit = OutContext.getOrCreateSymbol(
960 HasVectorFeature ? "__xray_FunctionExitVec" : "__xray_FunctionExit");
961 MCSymbol *BeginOfSled = OutContext.createTempSymbol("xray_sled_", true);
962 OutStreamer->emitLabel(BeginOfSled);
964 MCInstBuilder(SystemZ::BR).addReg(SystemZ::R14D));
967 MCInstBuilder(SystemZ::LLILF).addReg(SystemZ::R2D).addImm(0));
968 EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::J)
970 FuncExit, SystemZ::S_PLT, OutContext)));
971 if (FallthroughLabel)
972 OutStreamer->emitLabel(FallthroughLabel);
973 recordSled(BeginOfSled, MI, SledKind::FUNCTION_EXIT, 2);
974}
975
976// The *alignment* of 128-bit vector types is different between the software
977// and hardware vector ABIs. If the there is an externally visible use of a
978// vector type in the module it should be annotated with an attribute.
979void SystemZAsmPrinter::emitAttributes(Module &M) {
980 if (M.getModuleFlag("s390x-visible-vector-ABI")) {
981 bool HasVectorFeature =
982 TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureVector);
983 OutStreamer->emitGNUAttribute(8, HasVectorFeature ? 2 : 1);
984 }
985}
986
987// Convert a SystemZ-specific constant pool modifier into the associated
988// specifier.
990 switch (Modifier) {
991 case SystemZCP::TLSGD:
992 return SystemZ::S_TLSGD;
994 return SystemZ::S_TLSLDM;
996 return SystemZ::S_DTPOFF;
998 return SystemZ::S_NTPOFF;
999 }
1000 llvm_unreachable("Invalid SystemCPModifier!");
1001}
1002
1005 auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
1006
1007 const MCExpr *Expr = MCSymbolRefExpr::create(
1008 getSymbol(ZCPV->getGlobalValue()),
1009 getSpecifierFromModifier(ZCPV->getModifier()), OutContext);
1010 uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
1011
1012 OutStreamer->emitValue(Expr, Size);
1013}
1014
1015static void printFormattedRegName(const MCAsmInfo *MAI, unsigned RegNo,
1016 raw_ostream &OS) {
1017 const char *RegName;
1018 if (MAI->getAssemblerDialect() == AD_HLASM) {
1020 // Skip register prefix so that only register number is left
1021 assert(isalpha(RegName[0]) && isdigit(RegName[1]));
1022 OS << (RegName + 1);
1023 } else {
1025 OS << '%' << RegName;
1026 }
1027}
1028
1029static void printReg(unsigned Reg, const MCAsmInfo *MAI, raw_ostream &OS) {
1030 if (!Reg)
1031 OS << '0';
1032 else
1034}
1035
1036static void printOperand(const MCOperand &MCOp, const MCAsmInfo *MAI,
1037 raw_ostream &OS) {
1038 if (MCOp.isReg())
1039 printReg(MCOp.getReg(), MAI, OS);
1040 else if (MCOp.isImm())
1041 OS << MCOp.getImm();
1042 else if (MCOp.isExpr())
1043 MAI->printExpr(OS, *MCOp.getExpr());
1044 else
1045 llvm_unreachable("Invalid operand");
1046}
1047
1048static void printAddress(const MCAsmInfo *MAI, unsigned Base,
1049 const MCOperand &DispMO, unsigned Index,
1050 raw_ostream &OS) {
1051 printOperand(DispMO, MAI, OS);
1052 if (Base || Index) {
1053 OS << '(';
1054 if (Index) {
1055 printFormattedRegName(MAI, Index, OS);
1056 if (Base)
1057 OS << ',';
1058 }
1059 if (Base)
1061 OS << ')';
1062 }
1063}
1064
1066 const char *ExtraCode,
1067 raw_ostream &OS) {
1068 const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
1069 const MachineOperand &MO = MI->getOperand(OpNo);
1070 MCOperand MCOp;
1071 if (ExtraCode) {
1072 if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&
1073 SystemZ::GR128BitRegClass.contains(MO.getReg()))
1074 MCOp =
1075 MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));
1076 else
1077 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
1078 } else {
1079 SystemZMCInstLower Lower(MF->getContext(), *this);
1080 MCOp = Lower.lowerOperand(MO);
1081 }
1082 printOperand(MCOp, MAI, OS);
1083 return false;
1084}
1085
1087 unsigned OpNo,
1088 const char *ExtraCode,
1089 raw_ostream &OS) {
1090 if (ExtraCode && ExtraCode[0] && !ExtraCode[1]) {
1091 switch (ExtraCode[0]) {
1092 case 'A':
1093 // Unlike EmitMachineNode(), EmitSpecialNode(INLINEASM) does not call
1094 // setMemRefs(), so MI->memoperands() is empty and the alignment
1095 // information is not available.
1096 return false;
1097 case 'O':
1098 OS << MI->getOperand(OpNo + 1).getImm();
1099 return false;
1100 case 'R':
1101 ::printReg(MI->getOperand(OpNo).getReg(), MAI, OS);
1102 return false;
1103 }
1104 }
1105 printAddress(MAI, MI->getOperand(OpNo).getReg(),
1106 MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()),
1107 MI->getOperand(OpNo + 2).getReg(), OS);
1108 return false;
1109}
1110
1112 auto TT = OutContext.getTargetTriple();
1113 if (TT.isOSzOS()) {
1114 emitADASection();
1115 emitIDRLSection(M);
1116 }
1117 emitAttributes(M);
1118}
1119
1120void SystemZAsmPrinter::emitADASection() {
1121 OutStreamer->pushSection();
1122
1123 const unsigned PointerSize = getDataLayout().getPointerSize();
1124 OutStreamer->switchSection(getObjFileLowering().getADASection());
1125
1126 unsigned EmittedBytes = 0;
1127 for (auto &Entry : ADATable.getTable()) {
1128 const MCSymbol *Sym;
1129 unsigned SlotKind;
1130 std::tie(Sym, SlotKind) = Entry.first;
1131 unsigned Offset = Entry.second;
1132 assert(Offset == EmittedBytes && "Offset not as expected");
1133 (void)EmittedBytes;
1134#define EMIT_COMMENT(Str) \
1135 OutStreamer->AddComment(Twine("Offset ") \
1136 .concat(utostr(Offset)) \
1137 .concat(" " Str " ") \
1138 .concat(Sym->getName()));
1139 switch (SlotKind) {
1141 // Language Environment DLL logic requires function descriptors, for
1142 // imported functions, that are placed in the ADA to be 8 byte aligned.
1143 EMIT_COMMENT("function descriptor of");
1144 OutStreamer->emitValue(
1147 PointerSize);
1148 OutStreamer->emitValue(
1151 PointerSize);
1152 EmittedBytes += PointerSize * 2;
1153 break;
1155 EMIT_COMMENT("pointer to data symbol");
1156 OutStreamer->emitValue(
1159 PointerSize);
1160 EmittedBytes += PointerSize;
1161 break;
1164 Twine(Sym->getName()).concat("@indirect"));
1165 OutStreamer->emitAssignment(Alias,
1167 OutStreamer->emitSymbolAttribute(Alias, MCSA_IndirectSymbol);
1168
1169 EMIT_COMMENT("pointer to function descriptor");
1170 OutStreamer->emitValue(
1173 PointerSize);
1174 EmittedBytes += PointerSize;
1175 break;
1176 }
1177 default:
1178 llvm_unreachable("Unexpected slot kind");
1179 }
1180#undef EMIT_COMMENT
1181 }
1182 OutStreamer->popSection();
1183}
1184
1185static std::string getProductID(Module &M) {
1186 std::string ProductID;
1187 if (auto *MD = M.getModuleFlag("zos_product_id"))
1188 ProductID = cast<MDString>(MD)->getString().str();
1189 if (ProductID.empty())
1190 ProductID = "LLVM";
1191 return ProductID;
1192}
1193
1195 if (auto *VersionVal = mdconst::extract_or_null<ConstantInt>(
1196 M.getModuleFlag("zos_product_major_version")))
1197 return VersionVal->getZExtValue();
1198 return LLVM_VERSION_MAJOR;
1199}
1200
1202 if (auto *ReleaseVal = mdconst::extract_or_null<ConstantInt>(
1203 M.getModuleFlag("zos_product_minor_version")))
1204 return ReleaseVal->getZExtValue();
1205 return LLVM_VERSION_MINOR;
1206}
1207
1209 if (auto *PatchVal = mdconst::extract_or_null<ConstantInt>(
1210 M.getModuleFlag("zos_product_patchlevel")))
1211 return PatchVal->getZExtValue();
1212 return LLVM_VERSION_PATCH;
1213}
1214
1215static time_t getTranslationTime(Module &M) {
1216 std::time_t Time = 0;
1218 M.getModuleFlag("zos_translation_time"))) {
1219 long SecondsSinceEpoch = Val->getSExtValue();
1220 Time = static_cast<time_t>(SecondsSinceEpoch);
1221 }
1222 return Time;
1223}
1224
1225void SystemZAsmPrinter::emitIDRLSection(Module &M) {
1226 OutStreamer->pushSection();
1227 OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
1228 constexpr unsigned IDRLDataLength = 30;
1229 std::time_t Time = getTranslationTime(M);
1230
1231 uint32_t ProductVersion = getProductVersion(M);
1232 uint32_t ProductRelease = getProductRelease(M);
1233
1234 std::string ProductID = getProductID(M);
1235
1236 SmallString<IDRLDataLength + 1> TempStr;
1237 raw_svector_ostream O(TempStr);
1238 O << formatv("{0,-10}{1,0-2:d}{2,0-2:d}{3:%Y%m%d%H%M%S}{4,0-2}",
1239 ProductID.substr(0, 10).c_str(), ProductVersion, ProductRelease,
1240 llvm::sys::toUtcTime(Time), "0");
1241 SmallString<IDRLDataLength> Data;
1243
1244 OutStreamer->emitInt8(0); // Reserved.
1245 OutStreamer->emitInt8(3); // Format.
1246 OutStreamer->emitInt16(IDRLDataLength); // Length.
1247 OutStreamer->emitBytes(Data.str());
1248 OutStreamer->popSection();
1249}
1250
1252 if (TM.getTargetTriple().isOSzOS()) {
1253 // Emit symbol for the end of function if the z/OS target streamer
1254 // is used. This is needed to calculate the size of the function.
1255 MCSymbol *FnEndSym = createTempSymbol("func_end");
1256 OutStreamer->emitLabel(FnEndSym);
1257
1258 OutStreamer->pushSection();
1259 OutStreamer->switchSection(getObjFileLowering().getTextSection(),
1261 emitPPA1(FnEndSym);
1262 OutStreamer->popSection();
1263
1264 CurrentFnPPA1Sym = nullptr;
1265 CurrentFnEPMarkerSym = nullptr;
1266 }
1267}
1268
1269static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
1270 bool StackProtector, bool FPRMask, bool VRMask,
1271 bool EHBlock, bool HasArgAreaLength, bool HasName) {
1272 enum class PPA1Flag1 : uint8_t {
1273 DSA64Bit = (0x80 >> 0),
1274 VarArg = (0x80 >> 7),
1276 };
1277 enum class PPA1Flag2 : uint8_t {
1278 ExternalProcedure = (0x80 >> 0),
1279 STACKPROTECTOR = (0x80 >> 3),
1280 LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure)
1281 };
1282 enum class PPA1Flag3 : uint8_t {
1283 HasArgAreaLength = (0x80 >> 1),
1284 FPRMask = (0x80 >> 2),
1285 LLVM_MARK_AS_BITMASK_ENUM(HasArgAreaLength)
1286 };
1287 enum class PPA1Flag4 : uint8_t {
1288 EPMOffsetPresent = (0x80 >> 0),
1289 VRMask = (0x80 >> 2),
1290 EHBlock = (0x80 >> 3),
1291 ProcedureNamePresent = (0x80 >> 7),
1292 LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent)
1293 };
1294
1295 // Declare optional section flags that can be modified.
1296 auto Flags1 = PPA1Flag1(0);
1297 auto Flags2 = PPA1Flag2::ExternalProcedure;
1298 auto Flags3 = PPA1Flag3(0);
1299 auto Flags4 = PPA1Flag4::EPMOffsetPresent;
1300
1301 Flags1 |= PPA1Flag1::DSA64Bit;
1302
1303 if (VarArg)
1304 Flags1 |= PPA1Flag1::VarArg;
1305
1306 if (StackProtector)
1307 Flags2 |= PPA1Flag2::STACKPROTECTOR;
1308
1309 if (HasArgAreaLength)
1310 Flags3 |= PPA1Flag3::HasArgAreaLength; // Add emit ArgAreaLength flag.
1311
1312 // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in.
1313 if (FPRMask)
1314 Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag.
1315
1316 if (VRMask)
1317 Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag.
1318
1319 if (EHBlock)
1320 Flags4 |= PPA1Flag4::EHBlock; // Add optional EH block.
1321
1322 if (HasName)
1323 Flags4 |= PPA1Flag4::ProcedureNamePresent; // Add optional name block.
1324
1325 OutStreamer->AddComment("PPA1 Flags 1");
1326 if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit)
1327 OutStreamer->AddComment(" Bit 0: 1 = 64-bit DSA");
1328 else
1329 OutStreamer->AddComment(" Bit 0: 0 = 32-bit DSA");
1330 if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg)
1331 OutStreamer->AddComment(" Bit 7: 1 = Vararg function");
1332 OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1.
1333
1334 OutStreamer->AddComment("PPA1 Flags 2");
1335 if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure)
1336 OutStreamer->AddComment(" Bit 0: 1 = External procedure");
1337 if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR)
1338 OutStreamer->AddComment(" Bit 3: 1 = STACKPROTECT is enabled");
1339 else
1340 OutStreamer->AddComment(" Bit 3: 0 = STACKPROTECT is not enabled");
1341 OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2.
1342
1343 OutStreamer->AddComment("PPA1 Flags 3");
1344 if ((Flags3 & PPA1Flag3::HasArgAreaLength) == PPA1Flag3::HasArgAreaLength)
1345 OutStreamer->AddComment(
1346 " Bit 1: 1 = Argument Area Length is in optional area");
1347 if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask)
1348 OutStreamer->AddComment(" Bit 2: 1 = FP Reg Mask is in optional area");
1349 OutStreamer->emitInt8(
1350 static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections).
1351
1352 OutStreamer->AddComment("PPA1 Flags 4");
1353 if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask)
1354 OutStreamer->AddComment(" Bit 2: 1 = Vector Reg Mask is in optional area");
1355 if ((Flags4 & PPA1Flag4::EHBlock) == PPA1Flag4::EHBlock)
1356 OutStreamer->AddComment(" Bit 3: 1 = C++ EH block");
1357 if ((Flags4 & PPA1Flag4::ProcedureNamePresent) ==
1358 PPA1Flag4::ProcedureNamePresent)
1359 OutStreamer->AddComment(" Bit 7: 1 = Name Length and Name");
1360 OutStreamer->emitInt8(static_cast<uint8_t>(
1361 Flags4)); // Flags 4 (optional sections, always emit these).
1362}
1363
1364static void emitPPA1Name(std::unique_ptr<MCStreamer> &OutStreamer,
1365 StringRef OutName) {
1366 size_t NameSize = OutName.size();
1367 uint16_t OutSize;
1368 if (NameSize < UINT16_MAX) {
1369 OutSize = static_cast<uint16_t>(NameSize);
1370 } else {
1371 OutName = OutName.substr(0, UINT16_MAX);
1372 OutSize = UINT16_MAX;
1373 }
1374 // Emit padding to ensure that the next optional field word-aligned.
1375 uint8_t ExtraZeros = 4 - ((2 + OutSize) % 4);
1376
1377 SmallString<512> OutnameConv;
1378 ConverterEBCDIC::convertToEBCDIC(OutName, OutnameConv);
1379 OutName = OutnameConv.str();
1380
1381 OutStreamer->AddComment("Length of Name");
1382 OutStreamer->emitInt16(OutSize);
1383 OutStreamer->AddComment("Name of Function");
1384 OutStreamer->emitBytes(OutName);
1385 OutStreamer->emitZeros(ExtraZeros);
1386}
1387
1388void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
1389 assert(PPA2Sym != nullptr && "PPA2 Symbol not defined");
1390
1391 const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
1392 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
1393 const auto TargetHasVector = Subtarget.hasVector();
1394
1395 const SystemZMachineFunctionInfo *ZFI =
1396 MF->getInfo<SystemZMachineFunctionInfo>();
1397 const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>(
1398 Subtarget.getFrameLowering());
1399 const MachineFrameInfo &MFFrame = MF->getFrameInfo();
1400
1401 // Get saved GPR/FPR/VPR masks.
1402 const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
1403 uint16_t SavedGPRMask = 0;
1404 uint16_t SavedFPRMask = 0;
1405 uint8_t SavedVRMask = 0;
1406 int64_t OffsetFPR = 0;
1407 int64_t OffsetVR = 0;
1408 const int64_t TopOfStack =
1409 MFFrame.getOffsetAdjustment() + MFFrame.getStackSize();
1410
1411 // Loop over the spilled registers. The CalleeSavedInfo can't be used because
1412 // it does not contain all spilled registers.
1413 for (unsigned I = ZFI->getSpillGPRRegs().LowGPR,
1414 E = ZFI->getSpillGPRRegs().HighGPR;
1415 I && E && I <= E; ++I) {
1416 unsigned V = TRI->getEncodingValue((Register)I);
1417 assert(V < 16 && "GPR index out of range");
1418 SavedGPRMask |= 1 << (15 - V);
1419 }
1420
1421 for (auto &CS : CSI) {
1422 unsigned Reg = CS.getReg();
1423 unsigned I = TRI->getEncodingValue(Reg);
1424
1425 if (SystemZ::FP64BitRegClass.contains(Reg)) {
1426 assert(I < 16 && "FPR index out of range");
1427 SavedFPRMask |= 1 << (15 - I);
1428 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
1429 if (Temp < OffsetFPR)
1430 OffsetFPR = Temp;
1431 } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
1432 assert(I >= 16 && I <= 23 && "VPR index out of range");
1433 unsigned BitNum = I - 16;
1434 SavedVRMask |= 1 << (7 - BitNum);
1435 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
1436 if (Temp < OffsetVR)
1437 OffsetVR = Temp;
1438 }
1439 }
1440
1441 // Adjust the offset.
1442 OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0;
1443 OffsetVR += (OffsetVR < 0) ? TopOfStack : 0;
1444
1445 // Get alloca register.
1446 uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF));
1447 uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0;
1448 assert(AllocaReg < 16 && "Can't have alloca register larger than 15");
1449 (void)AllocaReg;
1450
1451 // Build FPR save area offset.
1452 uint32_t FrameAndFPROffset = 0;
1453 if (SavedFPRMask) {
1454 uint64_t FPRSaveAreaOffset = OffsetFPR;
1455 assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range");
1456
1457 FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
1458 FrameAndFPROffset |= FrameReg << 28; // Put into top 4 bits.
1459 }
1460
1461 // Build VR save area offset.
1462 uint32_t FrameAndVROffset = 0;
1463 if (TargetHasVector && SavedVRMask) {
1464 uint64_t VRSaveAreaOffset = OffsetVR;
1465 assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range");
1466
1467 FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
1468 FrameAndVROffset |= FrameReg << 28; // Put into top 4 bits.
1469 }
1470
1471 // Emit PPA1 section.
1472 OutStreamer->AddComment("PPA1");
1473 OutStreamer->emitLabel(CurrentFnPPA1Sym);
1474 OutStreamer->AddComment("Version");
1475 OutStreamer->emitInt8(0x02); // Version.
1476 OutStreamer->AddComment("LE Signature X'CE'");
1477 OutStreamer->emitInt8(0xCE); // CEL signature.
1478 OutStreamer->AddComment("Saved GPR Mask");
1479 OutStreamer->emitInt16(SavedGPRMask);
1480 OutStreamer->AddComment("Offset to PPA2");
1481 OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CurrentFnPPA1Sym, 4);
1482
1483 bool NeedEmitEHBlock = !MF->getLandingPads().empty();
1484
1485 // Optional Argument Area Length.
1486 // Note: This represents the length of the argument area that we reserve
1487 // in our stack for setting up arguments for calls to other
1488 // routines. If this optional field is not set, LE will reserve
1489 // 128 bytes for the argument area. This optional field is
1490 // created if greater than 128 bytes is required - to guarantee
1491 // the required space is reserved on stack extension in the new
1492 // extension. This optional field is also created if the
1493 // routine has alloca(). This may reduce stack space
1494 // if alloca() call causes a stack extension.
1495 bool HasArgAreaLength =
1496 (AllocaReg != 0) || (MFFrame.getMaxCallFrameSize() > 128);
1497
1498 bool HasName =
1499 MF->getFunction().hasName() && MF->getFunction().getName().size() > 0;
1500
1501 emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(),
1502 MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,
1503 TargetHasVector && SavedVRMask != 0, NeedEmitEHBlock,
1504 HasArgAreaLength, HasName);
1505
1506 OutStreamer->AddComment("Length/4 of Parms");
1507 OutStreamer->emitInt16(
1508 static_cast<uint16_t>(ZFI->getSizeOfFnParams() / 4)); // Parms/4.
1509 OutStreamer->AddComment("Length of Code");
1510 OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4);
1511
1512 if (HasArgAreaLength) {
1513 OutStreamer->AddComment("Argument Area Length");
1514 OutStreamer->emitInt32(MFFrame.getMaxCallFrameSize());
1515 }
1516
1517 // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).
1518 if (SavedFPRMask) {
1519 OutStreamer->AddComment("FPR mask");
1520 OutStreamer->emitInt16(SavedFPRMask);
1521 OutStreamer->AddComment("AR mask");
1522 OutStreamer->emitInt16(0); // AR Mask, unused currently.
1523 OutStreamer->AddComment("FPR Save Area Locator");
1524 OutStreamer->AddComment(Twine(" Bit 0-3: Register R")
1525 .concat(utostr(FrameAndFPROffset >> 28))
1526 .str());
1527 OutStreamer->AddComment(Twine(" Bit 4-31: Offset ")
1528 .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF))
1529 .str());
1530 OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with
1531 // register to add value to
1532 // (alloca reg).
1533 }
1534
1535 // Emit saved VR mask to VR save area.
1536 if (TargetHasVector && SavedVRMask) {
1537 OutStreamer->AddComment("VR mask");
1538 OutStreamer->emitInt8(SavedVRMask);
1539 OutStreamer->emitInt8(0); // Reserved.
1540 OutStreamer->emitInt16(0); // Also reserved.
1541 OutStreamer->AddComment("VR Save Area Locator");
1542 OutStreamer->AddComment(Twine(" Bit 0-3: Register R")
1543 .concat(utostr(FrameAndVROffset >> 28))
1544 .str());
1545 OutStreamer->AddComment(Twine(" Bit 4-31: Offset ")
1546 .concat(utostr(FrameAndVROffset & 0x0FFFFFFF))
1547 .str());
1548 OutStreamer->emitInt32(FrameAndVROffset);
1549 }
1550
1551 // Emit C++ EH information block
1552 const Function *Per = nullptr;
1553 if (NeedEmitEHBlock) {
1554 Per = dyn_cast<Function>(
1555 MF->getFunction().getPersonalityFn()->stripPointerCasts());
1556 MCSymbol *PersonalityRoutine =
1557 Per ? MF->getTarget().getSymbol(Per) : nullptr;
1558 assert(PersonalityRoutine && "Missing personality routine");
1559
1560 OutStreamer->AddComment("Version");
1561 OutStreamer->emitInt32(1);
1562 OutStreamer->AddComment("Flags");
1563 OutStreamer->emitInt32(0); // LSDA field is a WAS offset
1564 OutStreamer->AddComment("Personality routine");
1565 OutStreamer->emitInt64(ADATable.insert(
1566 PersonalityRoutine, SystemZII::MO_ADA_INDIRECT_FUNC_DESC));
1567 OutStreamer->AddComment("LSDA location");
1568 MCSymbol *GCCEH = MF->getContext().getOrCreateSymbol(
1569 Twine("GCC_except_table") + Twine(MF->getFunctionNumber()));
1570 OutStreamer->emitInt64(
1571 ADATable.insert(GCCEH, SystemZII::MO_ADA_DATA_SYMBOL_ADDR));
1572 }
1573
1574 // Emit name length and name optional section (0x01 of flags 4)
1575 if (HasName)
1576 emitPPA1Name(OutStreamer, MF->getFunction().getName());
1577
1578 // Emit offset to entry point optional section (0x80 of flags 4).
1579 OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym,
1580 4);
1581}
1582
1584 if (TM.getTargetTriple().isOSzOS())
1585 emitPPA2(M);
1587}
1588
1589void SystemZAsmPrinter::emitPPA2(Module &M) {
1590 OutStreamer->pushSection();
1591 OutStreamer->switchSection(getObjFileLowering().getTextSection(),
1593 MCContext &OutContext = OutStreamer->getContext();
1594 // Make CELQSTRT symbol.
1595 const char *StartSymbolName = "CELQSTRT";
1596 MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);
1597 OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_OSLinkage);
1598 OutStreamer->emitSymbolAttribute(CELQSTRT, MCSA_Global);
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 + null
1606 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 + null
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);
1624
1625 enum class PPA2MemberId : uint8_t {
1626 // See z/OS Language Environment Vendor Interfaces v2r5, p.23, for
1627 // 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 Flags
1639 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_env
1662 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") {
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
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 Marker
1724 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) << 5
1738 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 else
1756 OutStreamer->AddComment(" Bit 1: 0 = Non-leaf function");
1757 if (Flags & 0x04)
1758 OutStreamer->AddComment(" Bit 2: 1 = Uses alloca");
1759 else
1760 OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca");
1761 }
1762 OutStreamer->emitInt32(DSAAndFlags);
1763 }
1764
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 void
1775LLVMInitializeSystemZAsmPrinter() {
1777}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
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.
#define RegName(no)
#define I(x, y, z)
Definition MD5.cpp:57
Machine Check Debug Module
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:487
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
This file contains some functions that are useful when dealing with strings.
static MCInst lowerVecEltExtraction(const MachineInstr *MI, unsigned Opcode)
static uint8_t getSpecifierFromModifier(SystemZCP::SystemZCPModifier Modifier)
static void emitPPA1Name(std::unique_ptr< MCStreamer > &OutStreamer, StringRef OutName)
#define LOWER_LOW(NAME)
static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI, unsigned Opcode)
#define EMIT_COMMENT(Str)
static const MCSymbolRefExpr * getGlobalOffsetTable(MCContext &Context)
#define LOWER_HIGH(NAME)
static void printFormattedRegName(const MCAsmInfo *MAI, unsigned RegNo, raw_ostream &OS)
static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode)
static uint32_t getProductVersion(Module &M)
static std::string getProductID(Module &M)
static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode)
static void printAddress(const MCAsmInfo *MAI, unsigned Base, const MCOperand &DispMO, unsigned Index, raw_ostream &OS)
static time_t getTranslationTime(Module &M)
static const MCSymbolRefExpr * getTLSGetOffset(MCContext &Context)
static void emitPPA1Flags(std::unique_ptr< MCStreamer > &OutStreamer, bool VarArg, bool StackProtector, bool FPRMask, bool VRMask, bool EHBlock, bool HasArgAreaLength, bool HasName)
static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode)
static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, unsigned NumBytes, const MCSubtargetInfo &STI)
static MCInst lowerVecEltInsertion(const MachineInstr *MI, unsigned Opcode)
static uint32_t getProductRelease(Module &M)
static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode)
static uint32_t getProductPatch(Module &M)
static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode)
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
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
const MCAsmInfo * MAI
Target Asm Printer information.
Definition AsmPrinter.h:97
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:109
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:595
void recordSled(MCSymbol *Sled, const MachineInstr &MI, SledKind Kind, uint8_t Version=0)
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:101
MCSymbol * createTempSymbol(const Twine &Name) const
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:106
const DataLayout & getDataLayout() const
Return information about data layout.
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
LLVM_ABI unsigned getPointerSize(unsigned AS=0) const
The pointer representation size in bytes, rounded up to a whole number of bytes.
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition MCAsmInfo.h:64
unsigned getAssemblerDialect() const
Definition MCAsmInfo.h:560
void printExpr(raw_ostream &, const MCExpr &) const
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:343
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.
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
Definition MCContext.h:553
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.
MCInstBuilder & addExpr(const MCExpr *Val)
Add a new MCExpr operand.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
int64_t getImm() const
Definition MCInst.h:84
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
bool isImm() const
Definition MCInst.h:66
bool isReg() const
Definition MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
static const MCSpecifierExpr * create(const MCExpr *Expr, Spec S, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.cpp:743
Streaming machine code generation interface.
Definition MCStreamer.h:220
Generic base class for all target subtargets.
Represent a reference to a symbol from inside an expression.
Definition MCExpr.h:190
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:214
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
MachineInstrBundleIterator< const MachineInstr > const_iterator
Abstract base class for all machine specific constantpool value subclasses.
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.
MCContext & getContext() const
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Representation of each machine instruction.
ArrayRef< MachineMemOperand * >::iterator mmo_iterator
LLVM_ABI const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
@ MO_GlobalAddress
Address of a global value.
@ MO_ExternalSymbol
Name of external global symbol.
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.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition StringRef.h:573
constexpr size_t size() const
size - Get the string size.
Definition StringRef.h:146
void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override
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 emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
void emitFunctionEntryLabel() override
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
void emitEndOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the end of their file...
A SystemZ-specific constant pool value.
static const char * getRegisterName(MCRegister Reg)
static const char * getRegisterName(MCRegister Reg)
const SystemZInstrInfo * getInstrInfo() const override
const TargetFrameLowering * getFrameLowering() const override
std::pair< MCInst, const MCSubtargetInfo * > MCInstSTIPair
MCSymbol * getSymbol(const GlobalValue *GV) const
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
Definition Twine.cpp:17
Twine concat(const Twine &Suffix) const
Definition Twine.h:497
static Twine utohexstr(uint64_t Val)
Definition Twine.h:385
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an SmallVector or SmallString.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Language[]
Key for Kernel::Metadata::mLanguage.
@ Swift
Calling convention for Swift.
Definition CallingConv.h:69
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
LLVM_ABI std::error_code convertToEBCDIC(StringRef Source, SmallVectorImpl< char > &Result)
@ SHF_ALLOC
Definition ELF.h:1248
@ SHT_PROGBITS
Definition ELF.h:1147
@ SK_PPA1
Definition GOFF.h:192
@ SK_PPA2
Definition GOFF.h:193
unsigned getRegAsGR32(unsigned Reg)
const unsigned GR64Regs[16]
unsigned getRegAsGRH32(unsigned Reg)
unsigned getRegAsVR128(unsigned Reg)
unsigned getRegAsGR64(unsigned Reg)
constexpr size_t NameSize
Definition XCOFF.h:30
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:682
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.
Target & getTheSystemZTarget()
@ Offset
Definition DWP.cpp:532
@ Length
Definition DWP.cpp:532
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
std::string utostr(uint64_t X, bool isNeg=false)
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
Definition STLExtras.h:1150
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
FunctionAddr VTableAddr uintptr_t uintptr_t Version
Definition InstrProf.h:302
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:167
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
@ LLVM_MARK_AS_BITMASK_ENUM
Definition ModRef.h:37
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:189
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
@ MCSA_OSLinkage
symbol uses OS linkage (GOFF)
@ MCSA_IndirectSymbol
.indirect_symbol (MachO)
@ MCSA_Global
.type _foo, @gnu_unique_object
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...