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

source code of llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp