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
35 using namespace llvm;
36
37 // Return an RI instruction like MI with opcode Opcode, but with the
38 // GR64 register operands turned into GR32s.
lowerRILow(const MachineInstr * MI,unsigned Opcode)39 static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
40 if (MI->isCompare())
41 return MCInstBuilder(Opcode)
42 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
43 .addImm(MI->getOperand(1).getImm());
44 else
45 return MCInstBuilder(Opcode)
46 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
47 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))
48 .addImm(MI->getOperand(2).getImm());
49 }
50
51 // Return an RI instruction like MI with opcode Opcode, but with the
52 // GR64 register operands turned into GRH32s.
lowerRIHigh(const MachineInstr * MI,unsigned Opcode)53 static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {
54 if (MI->isCompare())
55 return MCInstBuilder(Opcode)
56 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
57 .addImm(MI->getOperand(1).getImm());
58 else
59 return MCInstBuilder(Opcode)
60 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
61 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg()))
62 .addImm(MI->getOperand(2).getImm());
63 }
64
65 // Return an RI instruction like MI with opcode Opcode, but with the
66 // R2 register turned into a GR64.
lowerRIEfLow(const MachineInstr * MI,unsigned Opcode)67 static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
68 return MCInstBuilder(Opcode)
69 .addReg(MI->getOperand(0).getReg())
70 .addReg(MI->getOperand(1).getReg())
71 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))
72 .addImm(MI->getOperand(3).getImm())
73 .addImm(MI->getOperand(4).getImm())
74 .addImm(MI->getOperand(5).getImm());
75 }
76
getTLSGetOffset(MCContext & Context)77 static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
78 StringRef Name = "__tls_get_offset";
79 return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
80 MCSymbolRefExpr::VK_PLT,
81 Context);
82 }
83
getGlobalOffsetTable(MCContext & Context)84 static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {
85 StringRef Name = "_GLOBAL_OFFSET_TABLE_";
86 return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
87 MCSymbolRefExpr::VK_None,
88 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.
lowerAlignmentHint(const MachineInstr * MI,MCInst & LoweredMI,unsigned Opcode)95 static 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(MCOperand::createImm(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.
lowerSubvectorLoad(const MachineInstr * MI,unsigned Opcode)120 static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {
121 return MCInstBuilder(Opcode)
122 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
123 .addReg(MI->getOperand(1).getReg())
124 .addImm(MI->getOperand(2).getImm())
125 .addReg(MI->getOperand(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.
lowerSubvectorStore(const MachineInstr * MI,unsigned Opcode)130 static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
131 return MCInstBuilder(Opcode)
132 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
133 .addReg(MI->getOperand(1).getReg())
134 .addImm(MI->getOperand(2).getImm())
135 .addReg(MI->getOperand(3).getReg())
136 .addImm(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.
emitCallInformation(CallType CT)144 void SystemZAsmPrinter::emitCallInformation(CallType CT) {
145 EmitToStreamer(*OutStreamer,
146 MCInstBuilder(SystemZ::BCRAsm)
147 .addImm(0)
148 .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
149 }
150
insert(const MCSymbol * Sym,unsigned SlotKind)151 uint32_t SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MCSymbol *Sym,
152 unsigned SlotKind) {
153 auto Key = std::make_pair(Sym, 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(Sym, SlotKind)] = NextDisplacement;
172 NextDisplacement += Length;
173
174 return Displacement;
175 }
176
177 uint32_t
insert(const MachineOperand MO)178 SystemZAsmPrinter::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(SymName);
187 assert(Sym && "No symbol");
188 } else
189 llvm_unreachable("Unexpected operand type");
190
191 unsigned ADAslotType = MO.getTargetFlags();
192 return insert(Sym, ADAslotType);
193 }
194
emitInstruction(const MachineInstr * MI)195 void 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::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(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(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(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(MI->getOperand(1));
330 Register TargetReg = MI->getOperand(0).getReg();
331
332 Register ADAReg = MI->getOperand(2).getReg();
333 Disp += MI->getOperand(3).getImm();
334 bool LoadAddr = MI->getOpcode() == SystemZ::ADA_ENTRY;
335
336 unsigned Op0 = LoadAddr ? SystemZ::LA : SystemZ::LG;
337 unsigned Op = TII->getOpcodeForOffset(Op0, 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(*OutStreamer, MCInstBuilder(Op)
355 .addReg(TargetReg)
356 .addReg(ADAReg)
357 .addImm(Disp)
358 .addReg(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, LoweredMI);
528 lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign);
529 break;
530
531 case SystemZ::VST:
532 Lower.lower(MI, LoweredMI);
533 lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign);
534 break;
535
536 case SystemZ::VLM:
537 Lower.lower(MI, LoweredMI);
538 lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign);
539 break;
540
541 case SystemZ::VSTM:
542 Lower.lower(MI, 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(DotSym);
627
628 const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
629 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, 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(DotSym);
640
641 const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
642 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, 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, Lower);
652 return;
653
654 case TargetOpcode::STACKMAP:
655 LowerSTACKMAP(*MI);
656 return;
657
658 case TargetOpcode::PATCHPOINT:
659 LowerPATCHPOINT(*MI, Lower);
660 return;
661
662 case SystemZ::EXRL_Pseudo: {
663 unsigned TargetInsOpc = MI->getOperand(0).getImm();
664 Register LenMinus1Reg = MI->getOperand(1).getReg();
665 Register DestReg = MI->getOperand(2).getReg();
666 int64_t DestDisp = MI->getOperand(3).getImm();
667 Register SrcReg = MI->getOperand(4).getReg();
668 int64_t SrcDisp = MI->getOperand(5).getImm();
669
670 SystemZTargetStreamer *TS = getTargetStreamer();
671 MCSymbol *DotSym = nullptr;
672 MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg)
673 .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp);
674 SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
675 SystemZTargetStreamer::EXRLT2SymMap::iterator I =
676 TS->EXRLTargets2Sym.find(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(DotSym, OutContext);
682 EmitToStreamer(
683 *OutStreamer,
684 MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));
685 return;
686 }
687
688 default:
689 Lower.lower(MI, LoweredMI);
690 break;
691 }
692 EmitToStreamer(*OutStreamer, LoweredMI);
693 }
694
695 // Emit the largest nop instruction smaller than or equal to NumBytes
696 // bytes. Return the size of nop emitted.
EmitNop(MCContext & OutContext,MCStreamer & OutStreamer,unsigned NumBytes,const MCSubtargetInfo & STI)697 static 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(DotSym, OutContext);
717 OutStreamer.emitLabel(DotSym);
718 OutStreamer.emitInstruction(
719 MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
720 return 6;
721 }
722 }
723
LowerFENTRY_CALL(const MachineInstr & MI,SystemZMCInstLower & Lower)724 void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
725 SystemZMCInstLower &Lower) {
726 MCContext &Ctx = MF->getContext();
727 if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
728 MCSymbol *DotSym = OutContext.createTempSymbol();
729 OutStreamer->pushSection();
730 OutStreamer->switchSection(
731 Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
732 OutStreamer->emitSymbolValue(DotSym, 8);
733 OutStreamer->popSection();
734 OutStreamer->emitLabel(DotSym);
735 }
736
737 if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
738 EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
739 return;
740 }
741
742 MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
743 const MCSymbolRefExpr *Op =
744 MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx);
745 OutStreamer->emitInstruction(
746 MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
747 getSubtargetInfo());
748 }
749
LowerSTACKMAP(const MachineInstr & MI)750 void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
751 auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo();
752
753 unsigned NumNOPBytes = MI.getOperand(1).getImm();
754
755 auto &Ctx = OutStreamer->getContext();
756 MCSymbol *MILabel = Ctx.createTempSymbol();
757 OutStreamer->emitLabel(MILabel);
758
759 SM.recordStackMap(*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(*MII);
773 if (MII->isCall())
774 break;
775 ++MII;
776 }
777
778 // Emit nops.
779 while (ShadowBytes < NumNOPBytes)
780 ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
781 getSubtargetInfo());
782 }
783
784 // Lower a patchpoint of the form:
785 // [<def>], <id>, <numBytes>, <target>, <numArgs>
LowerPATCHPOINT(const MachineInstr & MI,SystemZMCInstLower & Lower)786 void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
787 SystemZMCInstLower &Lower) {
788 auto &Ctx = OutStreamer->getContext();
789 MCSymbol *MILabel = Ctx.createTempSymbol();
790 OutStreamer->emitLabel(MILabel);
791
792 SM.recordPatchPoint(*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(ScratchIdx + 1);
805 ScratchReg = MI.getOperand(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(CalleeMO, 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, NumBytes - EncodedBytes,
841 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.
emitAttributes(Module & M)847 void SystemZAsmPrinter::emitAttributes(Module &M) {
848 if (M.getModuleFlag("s390x-visible-vector-ABI")) {
849 bool HasVectorFeature =
850 TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureVector);
851 OutStreamer->emitGNUAttribute(8, HasVectorFeature ? 2 : 1);
852 }
853 }
854
855 // Convert a SystemZ-specific constant pool modifier into the associated
856 // MCSymbolRefExpr variant kind.
857 static MCSymbolRefExpr::VariantKind
getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier)858 getModifierVariantKind(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
emitMachineConstantPoolValue(MachineConstantPoolValue * MCPV)868 void SystemZAsmPrinter::emitMachineConstantPoolValue(
869 MachineConstantPoolValue *MCPV) {
870 auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
871
872 const MCExpr *Expr =
873 MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
874 getModifierVariantKind(ZCPV->getModifier()),
875 OutContext);
876 uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
877
878 OutStreamer->emitValue(Expr, Size);
879 }
880
printFormattedRegName(const MCAsmInfo * MAI,unsigned RegNo,raw_ostream & OS)881 static void printFormattedRegName(const MCAsmInfo *MAI, unsigned RegNo,
882 raw_ostream &OS) {
883 const char *RegName = SystemZInstPrinter::getRegisterName(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
printOperand(const MCOperand & MCOp,const MCAsmInfo * MAI,raw_ostream & OS)892 static void printOperand(const MCOperand &MCOp, const MCAsmInfo *MAI,
893 raw_ostream &OS) {
894 if (MCOp.isReg()) {
895 if (!MCOp.getReg())
896 OS << '0';
897 else
898 printFormattedRegName(MAI, MCOp.getReg(), OS);
899 } else if (MCOp.isImm())
900 OS << MCOp.getImm();
901 else if (MCOp.isExpr())
902 MCOp.getExpr()->print(OS, MAI);
903 else
904 llvm_unreachable("Invalid operand");
905 }
906
printAddress(const MCAsmInfo * MAI,unsigned Base,const MCOperand & DispMO,unsigned Index,raw_ostream & OS)907 static void printAddress(const MCAsmInfo *MAI, unsigned Base,
908 const MCOperand &DispMO, unsigned Index,
909 raw_ostream &OS) {
910 printOperand(DispMO, MAI, OS);
911 if (Base || Index) {
912 OS << '(';
913 if (Index) {
914 printFormattedRegName(MAI, Index, OS);
915 if (Base)
916 OS << ',';
917 }
918 if (Base)
919 printFormattedRegName(MAI, Base, OS);
920 OS << ')';
921 }
922 }
923
PrintAsmOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & OS)924 bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
925 const char *ExtraCode,
926 raw_ostream &OS) {
927 const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
928 const MachineOperand &MO = MI->getOperand(OpNo);
929 MCOperand MCOp;
930 if (ExtraCode) {
931 if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&
932 SystemZ::GR128BitRegClass.contains(MO.getReg()))
933 MCOp =
934 MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));
935 else
936 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
937 } else {
938 SystemZMCInstLower Lower(MF->getContext(), *this);
939 MCOp = Lower.lowerOperand(MO);
940 }
941 printOperand(MCOp, MAI, OS);
942 return false;
943 }
944
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNo,const char * ExtraCode,raw_ostream & OS)945 bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
946 unsigned OpNo,
947 const char *ExtraCode,
948 raw_ostream &OS) {
949 printAddress(MAI, MI->getOperand(OpNo).getReg(),
950 MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()),
951 MI->getOperand(OpNo + 2).getReg(), OS);
952 return false;
953 }
954
emitEndOfAsmFile(Module & M)955 void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
956 auto TT = OutContext.getTargetTriple();
957 if (TT.isOSzOS()) {
958 emitADASection();
959 emitIDRLSection(M);
960 }
961 emitAttributes(M);
962 }
963
emitADASection()964 void SystemZAsmPrinter::emitADASection() {
965 OutStreamer->pushSection();
966
967 const unsigned PointerSize = getDataLayout().getPointerSize();
968 OutStreamer->switchSection(getObjFileLowering().getADASection());
969
970 unsigned EmittedBytes = 0;
971 for (auto &Entry : ADATable.getTable()) {
972 const MCSymbol *Sym;
973 unsigned SlotKind;
974 std::tie(Sym, SlotKind) = Entry.first;
975 unsigned Offset = Entry.second;
976 assert(Offset == EmittedBytes && "Offset not as expected");
977 (void)EmittedBytes;
978 #define EMIT_COMMENT(Str) \
979 OutStreamer->AddComment(Twine("Offset ") \
980 .concat(utostr(Offset)) \
981 .concat(" " Str " ") \
982 .concat(Sym->getName()));
983 switch (SlotKind) {
984 case SystemZII::MO_ADA_DIRECT_FUNC_DESC:
985 // Language Environment DLL logic requires function descriptors, for
986 // imported functions, that are placed in the ADA to be 8 byte aligned.
987 EMIT_COMMENT("function descriptor of");
988 OutStreamer->emitValue(
989 SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_RCon,
990 MCSymbolRefExpr::create(Sym, OutContext),
991 OutContext),
992 PointerSize);
993 OutStreamer->emitValue(
994 SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_VCon,
995 MCSymbolRefExpr::create(Sym, OutContext),
996 OutContext),
997 PointerSize);
998 EmittedBytes += PointerSize * 2;
999 break;
1000 case SystemZII::MO_ADA_DATA_SYMBOL_ADDR:
1001 EMIT_COMMENT("pointer to data symbol");
1002 OutStreamer->emitValue(
1003 SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_None,
1004 MCSymbolRefExpr::create(Sym, OutContext),
1005 OutContext),
1006 PointerSize);
1007 EmittedBytes += PointerSize;
1008 break;
1009 case SystemZII::MO_ADA_INDIRECT_FUNC_DESC: {
1010 MCSymbol *Alias = OutContext.createTempSymbol(
1011 Twine(Sym->getName()).concat("@indirect"));
1012 OutStreamer->emitAssignment(Alias,
1013 MCSymbolRefExpr::create(Sym, OutContext));
1014 OutStreamer->emitSymbolAttribute(Alias, MCSA_IndirectSymbol);
1015
1016 EMIT_COMMENT("pointer to function descriptor");
1017 OutStreamer->emitValue(
1018 SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_VCon,
1019 MCSymbolRefExpr::create(Alias, OutContext),
1020 OutContext),
1021 PointerSize);
1022 EmittedBytes += PointerSize;
1023 break;
1024 }
1025 default:
1026 llvm_unreachable("Unexpected slot kind");
1027 }
1028 #undef EMIT_COMMENT
1029 }
1030 OutStreamer->popSection();
1031 }
1032
getProductID(Module & M)1033 static std::string getProductID(Module &M) {
1034 std::string ProductID;
1035 if (auto *MD = M.getModuleFlag("zos_product_id"))
1036 ProductID = cast<MDString>(MD)->getString().str();
1037 if (ProductID.empty())
1038 ProductID = "LLVM";
1039 return ProductID;
1040 }
1041
getProductVersion(Module & M)1042 static uint32_t getProductVersion(Module &M) {
1043 if (auto *VersionVal = mdconst::extract_or_null<ConstantInt>(
1044 M.getModuleFlag("zos_product_major_version")))
1045 return VersionVal->getZExtValue();
1046 return LLVM_VERSION_MAJOR;
1047 }
1048
getProductRelease(Module & M)1049 static uint32_t getProductRelease(Module &M) {
1050 if (auto *ReleaseVal = mdconst::extract_or_null<ConstantInt>(
1051 M.getModuleFlag("zos_product_minor_version")))
1052 return ReleaseVal->getZExtValue();
1053 return LLVM_VERSION_MINOR;
1054 }
1055
getProductPatch(Module & M)1056 static uint32_t getProductPatch(Module &M) {
1057 if (auto *PatchVal = mdconst::extract_or_null<ConstantInt>(
1058 M.getModuleFlag("zos_product_patchlevel")))
1059 return PatchVal->getZExtValue();
1060 return LLVM_VERSION_PATCH;
1061 }
1062
getTranslationTime(Module & M)1063 static time_t getTranslationTime(Module &M) {
1064 std::time_t Time = 0;
1065 if (auto *Val = mdconst::extract_or_null<ConstantInt>(
1066 M.getModuleFlag("zos_translation_time"))) {
1067 long SecondsSinceEpoch = Val->getSExtValue();
1068 Time = static_cast<time_t>(SecondsSinceEpoch);
1069 }
1070 return Time;
1071 }
1072
emitIDRLSection(Module & M)1073 void SystemZAsmPrinter::emitIDRLSection(Module &M) {
1074 OutStreamer->pushSection();
1075 OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
1076 constexpr unsigned IDRLDataLength = 30;
1077 std::time_t Time = getTranslationTime(M);
1078
1079 uint32_t ProductVersion = getProductVersion(M);
1080 uint32_t ProductRelease = getProductRelease(M);
1081
1082 std::string ProductID = getProductID(M);
1083
1084 SmallString<IDRLDataLength + 1> TempStr;
1085 raw_svector_ostream O(TempStr);
1086 O << formatv("{0,-10}{1,0-2:d}{2,0-2:d}{3:%Y%m%d%H%M%S}{4,0-2}",
1087 ProductID.substr(0, 10).c_str(), ProductVersion, ProductRelease,
1088 llvm::sys::toUtcTime(Time), "0");
1089 SmallString<IDRLDataLength> Data;
1090 ConverterEBCDIC::convertToEBCDIC(TempStr, Data);
1091
1092 OutStreamer->emitInt8(0); // Reserved.
1093 OutStreamer->emitInt8(3); // Format.
1094 OutStreamer->emitInt16(IDRLDataLength); // Length.
1095 OutStreamer->emitBytes(Data.str());
1096 OutStreamer->popSection();
1097 }
1098
emitFunctionBodyEnd()1099 void SystemZAsmPrinter::emitFunctionBodyEnd() {
1100 if (TM.getTargetTriple().isOSzOS()) {
1101 // Emit symbol for the end of function if the z/OS target streamer
1102 // is used. This is needed to calculate the size of the function.
1103 MCSymbol *FnEndSym = createTempSymbol("func_end");
1104 OutStreamer->emitLabel(FnEndSym);
1105
1106 OutStreamer->pushSection();
1107 OutStreamer->switchSection(getObjFileLowering().getPPA1Section());
1108 emitPPA1(FnEndSym);
1109 OutStreamer->popSection();
1110
1111 CurrentFnPPA1Sym = nullptr;
1112 CurrentFnEPMarkerSym = nullptr;
1113 }
1114 }
1115
emitPPA1Flags(std::unique_ptr<MCStreamer> & OutStreamer,bool VarArg,bool StackProtector,bool FPRMask,bool VRMask,bool EHBlock,bool HasName)1116 static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
1117 bool StackProtector, bool FPRMask, bool VRMask,
1118 bool EHBlock, bool HasName) {
1119 enum class PPA1Flag1 : uint8_t {
1120 DSA64Bit = (0x80 >> 0),
1121 VarArg = (0x80 >> 7),
1122 LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit)
1123 };
1124 enum class PPA1Flag2 : uint8_t {
1125 ExternalProcedure = (0x80 >> 0),
1126 STACKPROTECTOR = (0x80 >> 3),
1127 LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure)
1128 };
1129 enum class PPA1Flag3 : uint8_t {
1130 FPRMask = (0x80 >> 2),
1131 LLVM_MARK_AS_BITMASK_ENUM(FPRMask)
1132 };
1133 enum class PPA1Flag4 : uint8_t {
1134 EPMOffsetPresent = (0x80 >> 0),
1135 VRMask = (0x80 >> 2),
1136 EHBlock = (0x80 >> 3),
1137 ProcedureNamePresent = (0x80 >> 7),
1138 LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent)
1139 };
1140
1141 // Declare optional section flags that can be modified.
1142 auto Flags1 = PPA1Flag1(0);
1143 auto Flags2 = PPA1Flag2::ExternalProcedure;
1144 auto Flags3 = PPA1Flag3(0);
1145 auto Flags4 = PPA1Flag4::EPMOffsetPresent;
1146
1147 Flags1 |= PPA1Flag1::DSA64Bit;
1148
1149 if (VarArg)
1150 Flags1 |= PPA1Flag1::VarArg;
1151
1152 if (StackProtector)
1153 Flags2 |= PPA1Flag2::STACKPROTECTOR;
1154
1155 // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in.
1156 if (FPRMask)
1157 Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag.
1158
1159 if (VRMask)
1160 Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag.
1161
1162 if (EHBlock)
1163 Flags4 |= PPA1Flag4::EHBlock; // Add optional EH block.
1164
1165 if (HasName)
1166 Flags4 |= PPA1Flag4::ProcedureNamePresent; // Add optional name block.
1167
1168 OutStreamer->AddComment("PPA1 Flags 1");
1169 if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit)
1170 OutStreamer->AddComment(" Bit 0: 1 = 64-bit DSA");
1171 else
1172 OutStreamer->AddComment(" Bit 0: 0 = 32-bit DSA");
1173 if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg)
1174 OutStreamer->AddComment(" Bit 7: 1 = Vararg function");
1175 OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1.
1176
1177 OutStreamer->AddComment("PPA1 Flags 2");
1178 if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure)
1179 OutStreamer->AddComment(" Bit 0: 1 = External procedure");
1180 if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR)
1181 OutStreamer->AddComment(" Bit 3: 1 = STACKPROTECT is enabled");
1182 else
1183 OutStreamer->AddComment(" Bit 3: 0 = STACKPROTECT is not enabled");
1184 OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2.
1185
1186 OutStreamer->AddComment("PPA1 Flags 3");
1187 if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask)
1188 OutStreamer->AddComment(" Bit 2: 1 = FP Reg Mask is in optional area");
1189 OutStreamer->emitInt8(
1190 static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections).
1191
1192 OutStreamer->AddComment("PPA1 Flags 4");
1193 if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask)
1194 OutStreamer->AddComment(" Bit 2: 1 = Vector Reg Mask is in optional area");
1195 if ((Flags4 & PPA1Flag4::EHBlock) == PPA1Flag4::EHBlock)
1196 OutStreamer->AddComment(" Bit 3: 1 = C++ EH block");
1197 if ((Flags4 & PPA1Flag4::ProcedureNamePresent) ==
1198 PPA1Flag4::ProcedureNamePresent)
1199 OutStreamer->AddComment(" Bit 7: 1 = Name Length and Name");
1200 OutStreamer->emitInt8(static_cast<uint8_t>(
1201 Flags4)); // Flags 4 (optional sections, always emit these).
1202 }
1203
emitPPA1Name(std::unique_ptr<MCStreamer> & OutStreamer,StringRef OutName)1204 static void emitPPA1Name(std::unique_ptr<MCStreamer> &OutStreamer,
1205 StringRef OutName) {
1206 size_t NameSize = OutName.size();
1207 uint16_t OutSize;
1208 if (NameSize < UINT16_MAX) {
1209 OutSize = static_cast<uint16_t>(NameSize);
1210 } else {
1211 OutName = OutName.substr(0, UINT16_MAX);
1212 OutSize = UINT16_MAX;
1213 }
1214 // Emit padding to ensure that the next optional field word-aligned.
1215 uint8_t ExtraZeros = 4 - ((2 + OutSize) % 4);
1216
1217 SmallString<512> OutnameConv;
1218 ConverterEBCDIC::convertToEBCDIC(OutName, OutnameConv);
1219 OutName = OutnameConv.str();
1220
1221 OutStreamer->AddComment("Length of Name");
1222 OutStreamer->emitInt16(OutSize);
1223 OutStreamer->AddComment("Name of Function");
1224 OutStreamer->emitBytes(OutName);
1225 OutStreamer->emitZeros(ExtraZeros);
1226 }
1227
emitPPA1(MCSymbol * FnEndSym)1228 void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
1229 assert(PPA2Sym != nullptr && "PPA2 Symbol not defined");
1230
1231 const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
1232 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
1233 const auto TargetHasVector = Subtarget.hasVector();
1234
1235 const SystemZMachineFunctionInfo *ZFI =
1236 MF->getInfo<SystemZMachineFunctionInfo>();
1237 const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>(
1238 Subtarget.getFrameLowering());
1239 const MachineFrameInfo &MFFrame = MF->getFrameInfo();
1240
1241 // Get saved GPR/FPR/VPR masks.
1242 const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
1243 uint16_t SavedGPRMask = 0;
1244 uint16_t SavedFPRMask = 0;
1245 uint8_t SavedVRMask = 0;
1246 int64_t OffsetFPR = 0;
1247 int64_t OffsetVR = 0;
1248 const int64_t TopOfStack =
1249 MFFrame.getOffsetAdjustment() + MFFrame.getStackSize();
1250
1251 // Loop over the spilled registers. The CalleeSavedInfo can't be used because
1252 // it does not contain all spilled registers.
1253 for (unsigned I = ZFI->getSpillGPRRegs().LowGPR,
1254 E = ZFI->getSpillGPRRegs().HighGPR;
1255 I && E && I <= E; ++I) {
1256 unsigned V = TRI->getEncodingValue((Register)I);
1257 assert(V < 16 && "GPR index out of range");
1258 SavedGPRMask |= 1 << (15 - V);
1259 }
1260
1261 for (auto &CS : CSI) {
1262 unsigned Reg = CS.getReg();
1263 unsigned I = TRI->getEncodingValue(Reg);
1264
1265 if (SystemZ::FP64BitRegClass.contains(Reg)) {
1266 assert(I < 16 && "FPR index out of range");
1267 SavedFPRMask |= 1 << (15 - I);
1268 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
1269 if (Temp < OffsetFPR)
1270 OffsetFPR = Temp;
1271 } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
1272 assert(I >= 16 && I <= 23 && "VPR index out of range");
1273 unsigned BitNum = I - 16;
1274 SavedVRMask |= 1 << (7 - BitNum);
1275 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
1276 if (Temp < OffsetVR)
1277 OffsetVR = Temp;
1278 }
1279 }
1280
1281 // Adjust the offset.
1282 OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0;
1283 OffsetVR += (OffsetVR < 0) ? TopOfStack : 0;
1284
1285 // Get alloca register.
1286 uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF));
1287 uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0;
1288 assert(AllocaReg < 16 && "Can't have alloca register larger than 15");
1289 (void)AllocaReg;
1290
1291 // Build FPR save area offset.
1292 uint32_t FrameAndFPROffset = 0;
1293 if (SavedFPRMask) {
1294 uint64_t FPRSaveAreaOffset = OffsetFPR;
1295 assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range");
1296
1297 FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
1298 FrameAndFPROffset |= FrameReg << 28; // Put into top 4 bits.
1299 }
1300
1301 // Build VR save area offset.
1302 uint32_t FrameAndVROffset = 0;
1303 if (TargetHasVector && SavedVRMask) {
1304 uint64_t VRSaveAreaOffset = OffsetVR;
1305 assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range");
1306
1307 FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
1308 FrameAndVROffset |= FrameReg << 28; // Put into top 4 bits.
1309 }
1310
1311 // Emit PPA1 section.
1312 OutStreamer->AddComment("PPA1");
1313 OutStreamer->emitLabel(CurrentFnPPA1Sym);
1314 OutStreamer->AddComment("Version");
1315 OutStreamer->emitInt8(0x02); // Version.
1316 OutStreamer->AddComment("LE Signature X'CE'");
1317 OutStreamer->emitInt8(0xCE); // CEL signature.
1318 OutStreamer->AddComment("Saved GPR Mask");
1319 OutStreamer->emitInt16(SavedGPRMask);
1320 OutStreamer->AddComment("Offset to PPA2");
1321 OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CurrentFnPPA1Sym, 4);
1322
1323 bool NeedEmitEHBlock = !MF->getLandingPads().empty();
1324
1325 bool HasName =
1326 MF->getFunction().hasName() && MF->getFunction().getName().size() > 0;
1327
1328 emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(),
1329 MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,
1330 TargetHasVector && SavedVRMask != 0, NeedEmitEHBlock, HasName);
1331
1332 OutStreamer->AddComment("Length/4 of Parms");
1333 OutStreamer->emitInt16(
1334 static_cast<uint16_t>(ZFI->getSizeOfFnParams() / 4)); // Parms/4.
1335 OutStreamer->AddComment("Length of Code");
1336 OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4);
1337
1338 // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).
1339 if (SavedFPRMask) {
1340 OutStreamer->AddComment("FPR mask");
1341 OutStreamer->emitInt16(SavedFPRMask);
1342 OutStreamer->AddComment("AR mask");
1343 OutStreamer->emitInt16(0); // AR Mask, unused currently.
1344 OutStreamer->AddComment("FPR Save Area Locator");
1345 OutStreamer->AddComment(Twine(" Bit 0-3: Register R")
1346 .concat(utostr(FrameAndFPROffset >> 28))
1347 .str());
1348 OutStreamer->AddComment(Twine(" Bit 4-31: Offset ")
1349 .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF))
1350 .str());
1351 OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with
1352 // register to add value to
1353 // (alloca reg).
1354 }
1355
1356 // Emit saved VR mask to VR save area.
1357 if (TargetHasVector && SavedVRMask) {
1358 OutStreamer->AddComment("VR mask");
1359 OutStreamer->emitInt8(SavedVRMask);
1360 OutStreamer->emitInt8(0); // Reserved.
1361 OutStreamer->emitInt16(0); // Also reserved.
1362 OutStreamer->AddComment("VR Save Area Locator");
1363 OutStreamer->AddComment(Twine(" Bit 0-3: Register R")
1364 .concat(utostr(FrameAndVROffset >> 28))
1365 .str());
1366 OutStreamer->AddComment(Twine(" Bit 4-31: Offset ")
1367 .concat(utostr(FrameAndVROffset & 0x0FFFFFFF))
1368 .str());
1369 OutStreamer->emitInt32(FrameAndVROffset);
1370 }
1371
1372 // Emit C++ EH information block
1373 const Function *Per = nullptr;
1374 if (NeedEmitEHBlock) {
1375 Per = dyn_cast<Function>(
1376 MF->getFunction().getPersonalityFn()->stripPointerCasts());
1377 MCSymbol *PersonalityRoutine =
1378 Per ? MF->getTarget().getSymbol(Per) : nullptr;
1379 assert(PersonalityRoutine && "Missing personality routine");
1380
1381 OutStreamer->AddComment("Version");
1382 OutStreamer->emitInt32(1);
1383 OutStreamer->AddComment("Flags");
1384 OutStreamer->emitInt32(0); // LSDA field is a WAS offset
1385 OutStreamer->AddComment("Personality routine");
1386 OutStreamer->emitInt64(ADATable.insert(
1387 PersonalityRoutine, SystemZII::MO_ADA_INDIRECT_FUNC_DESC));
1388 OutStreamer->AddComment("LSDA location");
1389 MCSymbol *GCCEH = MF->getContext().getOrCreateSymbol(
1390 Twine("GCC_except_table") + Twine(MF->getFunctionNumber()));
1391 OutStreamer->emitInt64(
1392 ADATable.insert(GCCEH, SystemZII::MO_ADA_DATA_SYMBOL_ADDR));
1393 }
1394
1395 // Emit name length and name optional section (0x01 of flags 4)
1396 if (HasName)
1397 emitPPA1Name(OutStreamer, MF->getFunction().getName());
1398
1399 // Emit offset to entry point optional section (0x80 of flags 4).
1400 OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym,
1401 4);
1402 }
1403
emitStartOfAsmFile(Module & M)1404 void SystemZAsmPrinter::emitStartOfAsmFile(Module &M) {
1405 if (TM.getTargetTriple().isOSzOS())
1406 emitPPA2(M);
1407 AsmPrinter::emitStartOfAsmFile(M);
1408 }
1409
emitPPA2(Module & M)1410 void SystemZAsmPrinter::emitPPA2(Module &M) {
1411 OutStreamer->pushSection();
1412 OutStreamer->switchSection(getObjFileLowering().getPPA2Section());
1413 MCContext &OutContext = OutStreamer->getContext();
1414 // Make CELQSTRT symbol.
1415 const char *StartSymbolName = "CELQSTRT";
1416 MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);
1417
1418 // Create symbol and assign to class field for use in PPA1.
1419 PPA2Sym = OutContext.createTempSymbol("PPA2", false);
1420 MCSymbol *DateVersionSym = OutContext.createTempSymbol("DVS", false);
1421
1422 std::time_t Time = getTranslationTime(M);
1423 SmallString<15> CompilationTime; // 14 + null
1424 raw_svector_ostream O(CompilationTime);
1425 O << formatv("{0:%Y%m%d%H%M%S}", llvm::sys::toUtcTime(Time));
1426
1427 uint32_t ProductVersion = getProductVersion(M),
1428 ProductRelease = getProductRelease(M),
1429 ProductPatch = getProductPatch(M);
1430
1431 SmallString<7> Version; // 6 + null
1432 raw_svector_ostream ostr(Version);
1433 ostr << formatv("{0,0-2:d}{1,0-2:d}{2,0-2:d}", ProductVersion, ProductRelease,
1434 ProductPatch);
1435
1436 // Drop 0 during conversion.
1437 SmallString<sizeof(CompilationTime) - 1> CompilationTimeStr;
1438 SmallString<sizeof(Version) - 1> VersionStr;
1439
1440 ConverterEBCDIC::convertToEBCDIC(CompilationTime, CompilationTimeStr);
1441 ConverterEBCDIC::convertToEBCDIC(Version, VersionStr);
1442
1443 enum class PPA2MemberId : uint8_t {
1444 // See z/OS Language Environment Vendor Interfaces v2r5, p.23, for
1445 // complete list. Only the C runtime is supported by this backend.
1446 LE_C_Runtime = 3,
1447 };
1448 enum class PPA2MemberSubId : uint8_t {
1449 // List of languages using the LE C runtime implementation.
1450 C = 0x00,
1451 CXX = 0x01,
1452 Swift = 0x03,
1453 Go = 0x60,
1454 LLVMBasedLang = 0xe7,
1455 };
1456 // PPA2 Flags
1457 enum class PPA2Flags : uint8_t {
1458 CompileForBinaryFloatingPoint = 0x80,
1459 CompiledWithXPLink = 0x01,
1460 CompiledUnitASCII = 0x04,
1461 HasServiceInfo = 0x20,
1462 };
1463
1464 PPA2MemberSubId MemberSubId = PPA2MemberSubId::LLVMBasedLang;
1465 if (auto *MD = M.getModuleFlag("zos_cu_language")) {
1466 StringRef Language = cast<MDString>(MD)->getString();
1467 MemberSubId = StringSwitch<PPA2MemberSubId>(Language)
1468 .Case("C", PPA2MemberSubId::C)
1469 .Case("C++", PPA2MemberSubId::CXX)
1470 .Case("Swift", PPA2MemberSubId::Swift)
1471 .Case("Go", PPA2MemberSubId::Go)
1472 .Default(PPA2MemberSubId::LLVMBasedLang);
1473 }
1474
1475 // Emit PPA2 section.
1476 OutStreamer->emitLabel(PPA2Sym);
1477 OutStreamer->emitInt8(static_cast<uint8_t>(PPA2MemberId::LE_C_Runtime));
1478 OutStreamer->emitInt8(static_cast<uint8_t>(MemberSubId));
1479 OutStreamer->emitInt8(0x22); // Member defined, c370_plist+c370_env
1480 OutStreamer->emitInt8(0x04); // Control level 4 (XPLink)
1481 OutStreamer->emitAbsoluteSymbolDiff(CELQSTRT, PPA2Sym, 4);
1482 OutStreamer->emitInt32(0x00000000);
1483 OutStreamer->emitAbsoluteSymbolDiff(DateVersionSym, PPA2Sym, 4);
1484 OutStreamer->emitInt32(
1485 0x00000000); // Offset to main entry point, always 0 (so says TR).
1486 uint8_t Flgs = static_cast<uint8_t>(PPA2Flags::CompileForBinaryFloatingPoint);
1487 Flgs |= static_cast<uint8_t>(PPA2Flags::CompiledWithXPLink);
1488
1489 if (auto *MD = M.getModuleFlag("zos_le_char_mode")) {
1490 const StringRef &CharMode = cast<MDString>(MD)->getString();
1491 if (CharMode == "ascii") {
1492 Flgs |= static_cast<uint8_t>(
1493 PPA2Flags::CompiledUnitASCII); // Setting bit for ASCII char. mode.
1494 } else if (CharMode != "ebcdic") {
1495 report_fatal_error(
1496 "Only ascii or ebcdic are valid values for zos_le_char_mode "
1497 "metadata");
1498 }
1499 }
1500
1501 OutStreamer->emitInt8(Flgs);
1502 OutStreamer->emitInt8(0x00); // Reserved.
1503 // No MD5 signature before timestamp.
1504 // No FLOAT(AFP(VOLATILE)).
1505 // Remaining 5 flag bits reserved.
1506 OutStreamer->emitInt16(0x0000); // 16 Reserved flag bits.
1507
1508 // Emit date and version section.
1509 OutStreamer->emitLabel(DateVersionSym);
1510 OutStreamer->emitBytes(CompilationTimeStr.str());
1511 OutStreamer->emitBytes(VersionStr.str());
1512
1513 OutStreamer->emitInt16(0x0000); // Service level string length.
1514
1515 // Emit 8 byte alignment.
1516 // Emit pointer to PPA2 label.
1517 OutStreamer->AddComment("A(PPA2-CELQSTRT)");
1518 OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CELQSTRT, 8);
1519 OutStreamer->popSection();
1520 }
1521
emitFunctionEntryLabel()1522 void SystemZAsmPrinter::emitFunctionEntryLabel() {
1523 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
1524
1525 if (Subtarget.getTargetTriple().isOSzOS()) {
1526 MCContext &OutContext = OutStreamer->getContext();
1527
1528 // Save information for later use.
1529 std::string N(MF->getFunction().hasName()
1530 ? Twine(MF->getFunction().getName()).concat("_").str()
1531 : "");
1532
1533 CurrentFnEPMarkerSym =
1534 OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true);
1535 CurrentFnPPA1Sym =
1536 OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true);
1537
1538 // EntryPoint Marker
1539 const MachineFrameInfo &MFFrame = MF->getFrameInfo();
1540 bool IsUsingAlloca = MFFrame.hasVarSizedObjects();
1541 uint32_t DSASize = MFFrame.getStackSize();
1542 bool IsLeaf = DSASize == 0 && MFFrame.getCalleeSavedInfo().empty();
1543
1544 // Set Flags.
1545 uint8_t Flags = 0;
1546 if (IsLeaf)
1547 Flags |= 0x08;
1548 if (IsUsingAlloca)
1549 Flags |= 0x04;
1550
1551 // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.
1552 uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5
1553 DSAAndFlags |= Flags;
1554
1555 // Emit entry point marker section.
1556 OutStreamer->AddComment("XPLINK Routine Layout Entry");
1557 OutStreamer->emitLabel(CurrentFnEPMarkerSym);
1558 OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
1559 OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
1560 OutStreamer->AddComment("Mark Type C'1'");
1561 OutStreamer->emitInt8(0xF1); // Mark Type.
1562 OutStreamer->AddComment("Offset to PPA1");
1563 OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym,
1564 4);
1565 if (OutStreamer->isVerboseAsm()) {
1566 OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
1567 OutStreamer->AddComment("Entry Flags");
1568 if (Flags & 0x08)
1569 OutStreamer->AddComment(" Bit 1: 1 = Leaf function");
1570 else
1571 OutStreamer->AddComment(" Bit 1: 0 = Non-leaf function");
1572 if (Flags & 0x04)
1573 OutStreamer->AddComment(" Bit 2: 1 = Uses alloca");
1574 else
1575 OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca");
1576 }
1577 OutStreamer->emitInt32(DSAAndFlags);
1578 }
1579
1580 AsmPrinter::emitFunctionEntryLabel();
1581 }
1582
1583 // Force static initialization.
LLVMInitializeSystemZAsmPrinter()1584 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() {
1585 RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
1586 }
1587