LLVM 18.0.0git
SystemZAsmPrinter.cpp
Go to the documentation of this file.
1//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Streams SystemZ assembly language and associated data, in the form of
10// MCInsts and MCExprs respectively.
11//
12//===----------------------------------------------------------------------===//
13
14#include "SystemZAsmPrinter.h"
18#include "SystemZMCInstLower.h"
24#include "llvm/IR/Mangler.h"
25#include "llvm/MC/MCExpr.h"
28#include "llvm/MC/MCStreamer.h"
31
32using namespace llvm;
33
34// Return an RI instruction like MI with opcode Opcode, but with the
35// GR64 register operands turned into GR32s.
36static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
37 if (MI->isCompare())
38 return MCInstBuilder(Opcode)
39 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
40 .addImm(MI->getOperand(1).getImm());
41 else
42 return MCInstBuilder(Opcode)
43 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
44 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))
45 .addImm(MI->getOperand(2).getImm());
46}
47
48// Return an RI instruction like MI with opcode Opcode, but with the
49// GR64 register operands turned into GRH32s.
50static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {
51 if (MI->isCompare())
52 return MCInstBuilder(Opcode)
53 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
54 .addImm(MI->getOperand(1).getImm());
55 else
56 return MCInstBuilder(Opcode)
57 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
58 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg()))
59 .addImm(MI->getOperand(2).getImm());
60}
61
62// Return an RI instruction like MI with opcode Opcode, but with the
63// R2 register turned into a GR64.
64static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
65 return MCInstBuilder(Opcode)
66 .addReg(MI->getOperand(0).getReg())
67 .addReg(MI->getOperand(1).getReg())
68 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))
69 .addImm(MI->getOperand(3).getImm())
70 .addImm(MI->getOperand(4).getImm())
71 .addImm(MI->getOperand(5).getImm());
72}
73
74static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
75 StringRef Name = "__tls_get_offset";
76 return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
78 Context);
79}
80
82 StringRef Name = "_GLOBAL_OFFSET_TABLE_";
83 return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
85 Context);
86}
87
88// MI is an instruction that accepts an optional alignment hint,
89// and which was already lowered to LoweredMI. If the alignment
90// of the original memory operand is known, update LoweredMI to
91// an instruction with the corresponding hint set.
92static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI,
93 unsigned Opcode) {
94 if (MI->memoperands_empty())
95 return;
96
97 Align Alignment = Align(16);
98 for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(),
99 EE = MI->memoperands_end(); MMOI != EE; ++MMOI)
100 if ((*MMOI)->getAlign() < Alignment)
101 Alignment = (*MMOI)->getAlign();
102
103 unsigned AlignmentHint = 0;
104 if (Alignment >= Align(16))
105 AlignmentHint = 4;
106 else if (Alignment >= Align(8))
107 AlignmentHint = 3;
108 if (AlignmentHint == 0)
109 return;
110
111 LoweredMI.setOpcode(Opcode);
112 LoweredMI.addOperand(MCOperand::createImm(AlignmentHint));
113}
114
115// MI loads the high part of a vector from memory. Return an instruction
116// that uses replicating vector load Opcode to do the same thing.
117static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {
118 return MCInstBuilder(Opcode)
119 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
120 .addReg(MI->getOperand(1).getReg())
121 .addImm(MI->getOperand(2).getImm())
122 .addReg(MI->getOperand(3).getReg());
123}
124
125// MI stores the high part of a vector to memory. Return an instruction
126// that uses elemental vector store Opcode to do the same thing.
127static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
128 return MCInstBuilder(Opcode)
129 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
130 .addReg(MI->getOperand(1).getReg())
131 .addImm(MI->getOperand(2).getImm())
132 .addReg(MI->getOperand(3).getReg())
133 .addImm(0);
134}
135
136// The XPLINK ABI requires that a no-op encoding the call type is emitted after
137// each call to a subroutine. This information can be used by the called
138// function to determine its entry point, e.g. for generating a backtrace. The
139// call type is encoded as a register number in the bcr instruction. See
140// enumeration CallType for the possible values.
141void SystemZAsmPrinter::emitCallInformation(CallType CT) {
143 MCInstBuilder(SystemZ::BCRAsm)
144 .addImm(0)
145 .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
146}
147
148uint32_t SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MCSymbol *Sym,
149 unsigned SlotKind) {
150 auto Key = std::make_pair(Sym, SlotKind);
151 auto It = Displacements.find(Key);
152
153 if (It != Displacements.end())
154 return (*It).second;
155
156 // Determine length of descriptor.
158 switch (SlotKind) {
160 Length = 2 * PointerSize;
161 break;
162 default:
164 break;
165 }
166
167 uint32_t Displacement = NextDisplacement;
168 Displacements[std::make_pair(Sym, SlotKind)] = NextDisplacement;
169 NextDisplacement += Length;
170
171 return Displacement;
172}
173
175SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MachineOperand MO) {
176 MCSymbol *Sym;
178 const GlobalValue *GV = MO.getGlobal();
179 Sym = MO.getParent()->getMF()->getTarget().getSymbol(GV);
180 assert(Sym && "No symbol");
181 } else if (MO.getType() == MachineOperand::MO_ExternalSymbol) {
182 const char *SymName = MO.getSymbolName();
183 Sym = MO.getParent()->getMF()->getContext().getOrCreateSymbol(SymName);
184 assert(Sym && "No symbol");
185 } else
186 llvm_unreachable("Unexpected operand type");
187
188 unsigned ADAslotType = MO.getTargetFlags();
189 return insert(Sym, ADAslotType);
190}
191
193 SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(),
194 getSubtargetInfo().getFeatureBits());
195
197 MCInst LoweredMI;
198 switch (MI->getOpcode()) {
199 case SystemZ::Return:
200 LoweredMI = MCInstBuilder(SystemZ::BR)
201 .addReg(SystemZ::R14D);
202 break;
203
204 case SystemZ::Return_XPLINK:
205 LoweredMI = MCInstBuilder(SystemZ::B)
206 .addReg(SystemZ::R7D)
207 .addImm(2)
208 .addReg(0);
209 break;
210
211 case SystemZ::CondReturn:
212 LoweredMI = MCInstBuilder(SystemZ::BCR)
213 .addImm(MI->getOperand(0).getImm())
214 .addImm(MI->getOperand(1).getImm())
215 .addReg(SystemZ::R14D);
216 break;
217
218 case SystemZ::CondReturn_XPLINK:
219 LoweredMI = MCInstBuilder(SystemZ::BC)
220 .addImm(MI->getOperand(0).getImm())
221 .addImm(MI->getOperand(1).getImm())
222 .addReg(SystemZ::R7D)
223 .addImm(2)
224 .addReg(0);
225 break;
226
227 case SystemZ::CRBReturn:
228 LoweredMI = MCInstBuilder(SystemZ::CRB)
229 .addReg(MI->getOperand(0).getReg())
230 .addReg(MI->getOperand(1).getReg())
231 .addImm(MI->getOperand(2).getImm())
232 .addReg(SystemZ::R14D)
233 .addImm(0);
234 break;
235
236 case SystemZ::CGRBReturn:
237 LoweredMI = MCInstBuilder(SystemZ::CGRB)
238 .addReg(MI->getOperand(0).getReg())
239 .addReg(MI->getOperand(1).getReg())
240 .addImm(MI->getOperand(2).getImm())
241 .addReg(SystemZ::R14D)
242 .addImm(0);
243 break;
244
245 case SystemZ::CIBReturn:
246 LoweredMI = MCInstBuilder(SystemZ::CIB)
247 .addReg(MI->getOperand(0).getReg())
248 .addImm(MI->getOperand(1).getImm())
249 .addImm(MI->getOperand(2).getImm())
250 .addReg(SystemZ::R14D)
251 .addImm(0);
252 break;
253
254 case SystemZ::CGIBReturn:
255 LoweredMI = MCInstBuilder(SystemZ::CGIB)
256 .addReg(MI->getOperand(0).getReg())
257 .addImm(MI->getOperand(1).getImm())
258 .addImm(MI->getOperand(2).getImm())
259 .addReg(SystemZ::R14D)
260 .addImm(0);
261 break;
262
263 case SystemZ::CLRBReturn:
264 LoweredMI = MCInstBuilder(SystemZ::CLRB)
265 .addReg(MI->getOperand(0).getReg())
266 .addReg(MI->getOperand(1).getReg())
267 .addImm(MI->getOperand(2).getImm())
268 .addReg(SystemZ::R14D)
269 .addImm(0);
270 break;
271
272 case SystemZ::CLGRBReturn:
273 LoweredMI = MCInstBuilder(SystemZ::CLGRB)
274 .addReg(MI->getOperand(0).getReg())
275 .addReg(MI->getOperand(1).getReg())
276 .addImm(MI->getOperand(2).getImm())
277 .addReg(SystemZ::R14D)
278 .addImm(0);
279 break;
280
281 case SystemZ::CLIBReturn:
282 LoweredMI = MCInstBuilder(SystemZ::CLIB)
283 .addReg(MI->getOperand(0).getReg())
284 .addImm(MI->getOperand(1).getImm())
285 .addImm(MI->getOperand(2).getImm())
286 .addReg(SystemZ::R14D)
287 .addImm(0);
288 break;
289
290 case SystemZ::CLGIBReturn:
291 LoweredMI = MCInstBuilder(SystemZ::CLGIB)
292 .addReg(MI->getOperand(0).getReg())
293 .addImm(MI->getOperand(1).getImm())
294 .addImm(MI->getOperand(2).getImm())
295 .addReg(SystemZ::R14D)
296 .addImm(0);
297 break;
298
299 case SystemZ::CallBRASL_XPLINK64:
301 MCInstBuilder(SystemZ::BRASL)
302 .addReg(SystemZ::R7D)
303 .addExpr(Lower.getExpr(MI->getOperand(0),
305 emitCallInformation(CallType::BRASL7);
306 return;
307
308 case SystemZ::CallBASR_XPLINK64:
310 .addReg(SystemZ::R7D)
311 .addReg(MI->getOperand(0).getReg()));
312 emitCallInformation(CallType::BASR76);
313 return;
314
315 case SystemZ::CallBASR_STACKEXT:
317 .addReg(SystemZ::R3D)
318 .addReg(MI->getOperand(0).getReg()));
319 emitCallInformation(CallType::BASR33);
320 return;
321
322 case SystemZ::ADA_ENTRY_VALUE:
323 case SystemZ::ADA_ENTRY: {
324 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
325 const SystemZInstrInfo *TII = Subtarget.getInstrInfo();
326 uint32_t Disp = ADATable.insert(MI->getOperand(1));
327 Register TargetReg = MI->getOperand(0).getReg();
328
329 Register ADAReg = MI->getOperand(2).getReg();
330 Disp += MI->getOperand(3).getImm();
331 bool LoadAddr = MI->getOpcode() == SystemZ::ADA_ENTRY;
332
333 unsigned Op0 = LoadAddr ? SystemZ::LA : SystemZ::LG;
334 unsigned Op = TII->getOpcodeForOffset(Op0, Disp);
335
336 Register IndexReg = 0;
337 if (!Op) {
338 if (TargetReg != ADAReg) {
339 IndexReg = TargetReg;
340 // Use TargetReg to store displacement.
343 MCInstBuilder(SystemZ::LLILF).addReg(TargetReg).addImm(Disp));
344 } else
347 MCInstBuilder(SystemZ::ALGFI).addReg(TargetReg).addImm(Disp));
348 Disp = 0;
349 Op = Op0;
350 }
352 .addReg(TargetReg)
353 .addReg(IndexReg)
354 .addImm(Disp)
355 .addReg(ADAReg));
356
357 return;
358 }
359 case SystemZ::CallBRASL:
360 LoweredMI = MCInstBuilder(SystemZ::BRASL)
361 .addReg(SystemZ::R14D)
362 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
363 break;
364
365 case SystemZ::CallBASR:
366 LoweredMI = MCInstBuilder(SystemZ::BASR)
367 .addReg(SystemZ::R14D)
368 .addReg(MI->getOperand(0).getReg());
369 break;
370
371 case SystemZ::CallJG:
372 LoweredMI = MCInstBuilder(SystemZ::JG)
373 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
374 break;
375
376 case SystemZ::CallBRCL:
377 LoweredMI = MCInstBuilder(SystemZ::BRCL)
378 .addImm(MI->getOperand(0).getImm())
379 .addImm(MI->getOperand(1).getImm())
380 .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT));
381 break;
382
383 case SystemZ::CallBR:
384 LoweredMI = MCInstBuilder(SystemZ::BR)
385 .addReg(MI->getOperand(0).getReg());
386 break;
387
388 case SystemZ::CallBCR:
389 LoweredMI = MCInstBuilder(SystemZ::BCR)
390 .addImm(MI->getOperand(0).getImm())
391 .addImm(MI->getOperand(1).getImm())
392 .addReg(MI->getOperand(2).getReg());
393 break;
394
395 case SystemZ::CRBCall:
396 LoweredMI = MCInstBuilder(SystemZ::CRB)
397 .addReg(MI->getOperand(0).getReg())
398 .addReg(MI->getOperand(1).getReg())
399 .addImm(MI->getOperand(2).getImm())
400 .addReg(MI->getOperand(3).getReg())
401 .addImm(0);
402 break;
403
404 case SystemZ::CGRBCall:
405 LoweredMI = MCInstBuilder(SystemZ::CGRB)
406 .addReg(MI->getOperand(0).getReg())
407 .addReg(MI->getOperand(1).getReg())
408 .addImm(MI->getOperand(2).getImm())
409 .addReg(MI->getOperand(3).getReg())
410 .addImm(0);
411 break;
412
413 case SystemZ::CIBCall:
414 LoweredMI = MCInstBuilder(SystemZ::CIB)
415 .addReg(MI->getOperand(0).getReg())
416 .addImm(MI->getOperand(1).getImm())
417 .addImm(MI->getOperand(2).getImm())
418 .addReg(MI->getOperand(3).getReg())
419 .addImm(0);
420 break;
421
422 case SystemZ::CGIBCall:
423 LoweredMI = MCInstBuilder(SystemZ::CGIB)
424 .addReg(MI->getOperand(0).getReg())
425 .addImm(MI->getOperand(1).getImm())
426 .addImm(MI->getOperand(2).getImm())
427 .addReg(MI->getOperand(3).getReg())
428 .addImm(0);
429 break;
430
431 case SystemZ::CLRBCall:
432 LoweredMI = MCInstBuilder(SystemZ::CLRB)
433 .addReg(MI->getOperand(0).getReg())
434 .addReg(MI->getOperand(1).getReg())
435 .addImm(MI->getOperand(2).getImm())
436 .addReg(MI->getOperand(3).getReg())
437 .addImm(0);
438 break;
439
440 case SystemZ::CLGRBCall:
441 LoweredMI = MCInstBuilder(SystemZ::CLGRB)
442 .addReg(MI->getOperand(0).getReg())
443 .addReg(MI->getOperand(1).getReg())
444 .addImm(MI->getOperand(2).getImm())
445 .addReg(MI->getOperand(3).getReg())
446 .addImm(0);
447 break;
448
449 case SystemZ::CLIBCall:
450 LoweredMI = MCInstBuilder(SystemZ::CLIB)
451 .addReg(MI->getOperand(0).getReg())
452 .addImm(MI->getOperand(1).getImm())
453 .addImm(MI->getOperand(2).getImm())
454 .addReg(MI->getOperand(3).getReg())
455 .addImm(0);
456 break;
457
458 case SystemZ::CLGIBCall:
459 LoweredMI = MCInstBuilder(SystemZ::CLGIB)
460 .addReg(MI->getOperand(0).getReg())
461 .addImm(MI->getOperand(1).getImm())
462 .addImm(MI->getOperand(2).getImm())
463 .addReg(MI->getOperand(3).getReg())
464 .addImm(0);
465 break;
466
467 case SystemZ::TLS_GDCALL:
468 LoweredMI = MCInstBuilder(SystemZ::BRASL)
469 .addReg(SystemZ::R14D)
471 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD));
472 break;
473
474 case SystemZ::TLS_LDCALL:
475 LoweredMI = MCInstBuilder(SystemZ::BRASL)
476 .addReg(SystemZ::R14D)
478 .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM));
479 break;
480
481 case SystemZ::GOT:
482 LoweredMI = MCInstBuilder(SystemZ::LARL)
483 .addReg(MI->getOperand(0).getReg())
485 break;
486
487 case SystemZ::IILF64:
488 LoweredMI = MCInstBuilder(SystemZ::IILF)
489 .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
490 .addImm(MI->getOperand(2).getImm());
491 break;
492
493 case SystemZ::IIHF64:
494 LoweredMI = MCInstBuilder(SystemZ::IIHF)
495 .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
496 .addImm(MI->getOperand(2).getImm());
497 break;
498
499 case SystemZ::RISBHH:
500 case SystemZ::RISBHL:
501 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
502 break;
503
504 case SystemZ::RISBLH:
505 case SystemZ::RISBLL:
506 LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
507 break;
508
509 case SystemZ::VLVGP32:
510 LoweredMI = MCInstBuilder(SystemZ::VLVGP)
511 .addReg(MI->getOperand(0).getReg())
512 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg()))
513 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()));
514 break;
515
516 case SystemZ::VLR32:
517 case SystemZ::VLR64:
518 LoweredMI = MCInstBuilder(SystemZ::VLR)
519 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
520 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()));
521 break;
522
523 case SystemZ::VL:
524 Lower.lower(MI, LoweredMI);
525 lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign);
526 break;
527
528 case SystemZ::VST:
529 Lower.lower(MI, LoweredMI);
530 lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign);
531 break;
532
533 case SystemZ::VLM:
534 Lower.lower(MI, LoweredMI);
535 lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign);
536 break;
537
538 case SystemZ::VSTM:
539 Lower.lower(MI, LoweredMI);
540 lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign);
541 break;
542
543 case SystemZ::VL32:
544 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF);
545 break;
546
547 case SystemZ::VL64:
548 LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG);
549 break;
550
551 case SystemZ::VST32:
552 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF);
553 break;
554
555 case SystemZ::VST64:
556 LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG);
557 break;
558
559 case SystemZ::LFER:
560 LoweredMI = MCInstBuilder(SystemZ::VLGVF)
561 .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg()))
562 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()))
563 .addReg(0).addImm(0);
564 break;
565
566 case SystemZ::LEFR:
567 LoweredMI = MCInstBuilder(SystemZ::VLVGF)
568 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
569 .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
570 .addReg(MI->getOperand(1).getReg())
571 .addReg(0).addImm(0);
572 break;
573
574#define LOWER_LOW(NAME) \
575 case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
576
577 LOWER_LOW(IILL);
578 LOWER_LOW(IILH);
579 LOWER_LOW(TMLL);
580 LOWER_LOW(TMLH);
581 LOWER_LOW(NILL);
582 LOWER_LOW(NILH);
583 LOWER_LOW(NILF);
584 LOWER_LOW(OILL);
585 LOWER_LOW(OILH);
586 LOWER_LOW(OILF);
587 LOWER_LOW(XILF);
588
589#undef LOWER_LOW
590
591#define LOWER_HIGH(NAME) \
592 case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
593
594 LOWER_HIGH(IIHL);
595 LOWER_HIGH(IIHH);
596 LOWER_HIGH(TMHL);
597 LOWER_HIGH(TMHH);
598 LOWER_HIGH(NIHL);
599 LOWER_HIGH(NIHH);
600 LOWER_HIGH(NIHF);
601 LOWER_HIGH(OIHL);
602 LOWER_HIGH(OIHH);
603 LOWER_HIGH(OIHF);
604 LOWER_HIGH(XIHF);
605
606#undef LOWER_HIGH
607
608 case SystemZ::Serialize:
609 if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
610 LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
611 .addImm(14).addReg(SystemZ::R0D);
612 else
613 LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
614 .addImm(15).addReg(SystemZ::R0D);
615 break;
616
617 // We want to emit "j .+2" for traps, jumping to the relative immediate field
618 // of the jump instruction, which is an illegal instruction. We cannot emit a
619 // "." symbol, so create and emit a temp label before the instruction and use
620 // that instead.
621 case SystemZ::Trap: {
623 OutStreamer->emitLabel(DotSym);
624
626 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
627 LoweredMI = MCInstBuilder(SystemZ::J)
628 .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
629 }
630 break;
631
632 // Conditional traps will create a branch on condition instruction that jumps
633 // to the relative immediate field of the jump instruction. (eg. "jo .+2")
634 case SystemZ::CondTrap: {
636 OutStreamer->emitLabel(DotSym);
637
639 const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
640 LoweredMI = MCInstBuilder(SystemZ::BRC)
641 .addImm(MI->getOperand(0).getImm())
642 .addImm(MI->getOperand(1).getImm())
643 .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
644 }
645 break;
646
647 case TargetOpcode::FENTRY_CALL:
648 LowerFENTRY_CALL(*MI, Lower);
649 return;
650
651 case TargetOpcode::STACKMAP:
652 LowerSTACKMAP(*MI);
653 return;
654
655 case TargetOpcode::PATCHPOINT:
656 LowerPATCHPOINT(*MI, Lower);
657 return;
658
659 case SystemZ::EXRL_Pseudo: {
660 unsigned TargetInsOpc = MI->getOperand(0).getImm();
661 Register LenMinus1Reg = MI->getOperand(1).getReg();
662 Register DestReg = MI->getOperand(2).getReg();
663 int64_t DestDisp = MI->getOperand(3).getImm();
664 Register SrcReg = MI->getOperand(4).getReg();
665 int64_t SrcDisp = MI->getOperand(5).getImm();
666
667 SystemZTargetStreamer *TS = getTargetStreamer();
668 MCSymbol *DotSym = nullptr;
669 MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg)
670 .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp);
672 SystemZTargetStreamer::EXRLT2SymMap::iterator I =
673 TS->EXRLTargets2Sym.find(ET_STI);
674 if (I != TS->EXRLTargets2Sym.end())
675 DotSym = I->second;
676 else
677 TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
681 MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));
682 return;
683 }
684
685 default:
686 Lower.lower(MI, LoweredMI);
687 break;
688 }
689 EmitToStreamer(*OutStreamer, LoweredMI);
690}
691
692// Emit the largest nop instruction smaller than or equal to NumBytes
693// bytes. Return the size of nop emitted.
694static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
695 unsigned NumBytes, const MCSubtargetInfo &STI) {
696 if (NumBytes < 2) {
697 llvm_unreachable("Zero nops?");
698 return 0;
699 }
700 else if (NumBytes < 4) {
701 OutStreamer.emitInstruction(
702 MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
703 return 2;
704 }
705 else if (NumBytes < 6) {
706 OutStreamer.emitInstruction(
707 MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
708 STI);
709 return 4;
710 }
711 else {
712 MCSymbol *DotSym = OutContext.createTempSymbol();
713 const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
714 OutStreamer.emitLabel(DotSym);
715 OutStreamer.emitInstruction(
716 MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
717 return 6;
718 }
719}
720
721void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
723 MCContext &Ctx = MF->getContext();
724 if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
726 OutStreamer->pushSection();
727 OutStreamer->switchSection(
728 Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
729 OutStreamer->emitSymbolValue(DotSym, 8);
730 OutStreamer->popSection();
731 OutStreamer->emitLabel(DotSym);
732 }
733
734 if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
736 return;
737 }
738
739 MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
740 const MCSymbolRefExpr *Op =
742 OutStreamer->emitInstruction(
743 MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
745}
746
747void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
748 auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo();
749
750 unsigned NumNOPBytes = MI.getOperand(1).getImm();
751
752 auto &Ctx = OutStreamer->getContext();
753 MCSymbol *MILabel = Ctx.createTempSymbol();
754 OutStreamer->emitLabel(MILabel);
755
756 SM.recordStackMap(*MILabel, MI);
757 assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
758
759 // Scan ahead to trim the shadow.
760 unsigned ShadowBytes = 0;
761 const MachineBasicBlock &MBB = *MI.getParent();
763 ++MII;
764 while (ShadowBytes < NumNOPBytes) {
765 if (MII == MBB.end() ||
766 MII->getOpcode() == TargetOpcode::PATCHPOINT ||
767 MII->getOpcode() == TargetOpcode::STACKMAP)
768 break;
769 ShadowBytes += TII->getInstSizeInBytes(*MII);
770 if (MII->isCall())
771 break;
772 ++MII;
773 }
774
775 // Emit nops.
776 while (ShadowBytes < NumNOPBytes)
777 ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
779}
780
781// Lower a patchpoint of the form:
782// [<def>], <id>, <numBytes>, <target>, <numArgs>
783void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
785 auto &Ctx = OutStreamer->getContext();
786 MCSymbol *MILabel = Ctx.createTempSymbol();
787 OutStreamer->emitLabel(MILabel);
788
789 SM.recordPatchPoint(*MILabel, MI);
790 PatchPointOpers Opers(&MI);
791
792 unsigned EncodedBytes = 0;
793 const MachineOperand &CalleeMO = Opers.getCallTarget();
794
795 if (CalleeMO.isImm()) {
796 uint64_t CallTarget = CalleeMO.getImm();
797 if (CallTarget) {
798 unsigned ScratchIdx = -1;
799 unsigned ScratchReg = 0;
800 do {
801 ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
802 ScratchReg = MI.getOperand(ScratchIdx).getReg();
803 } while (ScratchReg == SystemZ::R0D);
804
805 // Materialize the call target address
807 .addReg(ScratchReg)
808 .addImm(CallTarget & 0xFFFFFFFF));
809 EncodedBytes += 6;
810 if (CallTarget >> 32) {
812 .addReg(ScratchReg)
813 .addImm(CallTarget >> 32));
814 EncodedBytes += 6;
815 }
816
818 .addReg(SystemZ::R14D)
819 .addReg(ScratchReg));
820 EncodedBytes += 2;
821 }
822 } else if (CalleeMO.isGlobal()) {
823 const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT);
825 .addReg(SystemZ::R14D)
826 .addExpr(Expr));
827 EncodedBytes += 6;
828 }
829
830 // Emit padding.
831 unsigned NumBytes = Opers.getNumPatchBytes();
832 assert(NumBytes >= EncodedBytes &&
833 "Patchpoint can't request size less than the length of a call.");
834 assert((NumBytes - EncodedBytes) % 2 == 0 &&
835 "Invalid number of NOP bytes requested!");
836 while (EncodedBytes < NumBytes)
837 EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
839}
840
841// The *alignment* of 128-bit vector types is different between the software
842// and hardware vector ABIs. If the there is an externally visible use of a
843// vector type in the module it should be annotated with an attribute.
844void SystemZAsmPrinter::emitAttributes(Module &M) {
845 if (M.getModuleFlag("s390x-visible-vector-ABI")) {
846 bool HasVectorFeature =
847 TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureVector);
848 OutStreamer->emitGNUAttribute(8, HasVectorFeature ? 2 : 1);
849 }
850}
851
852// Convert a SystemZ-specific constant pool modifier into the associated
853// MCSymbolRefExpr variant kind.
856 switch (Modifier) {
861 }
862 llvm_unreachable("Invalid SystemCPModifier!");
863}
864
867 auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
868
869 const MCExpr *Expr =
870 MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
871 getModifierVariantKind(ZCPV->getModifier()),
872 OutContext);
873 uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
874
875 OutStreamer->emitValue(Expr, Size);
876}
877
878static void printFormattedRegName(const MCAsmInfo *MAI, unsigned RegNo,
879 raw_ostream &OS) {
880 const char *RegName = SystemZInstPrinter::getRegisterName(RegNo);
881 if (MAI->getAssemblerDialect() == AD_HLASM) {
882 // Skip register prefix so that only register number is left
883 assert(isalpha(RegName[0]) && isdigit(RegName[1]));
884 OS << (RegName + 1);
885 } else
886 OS << '%' << RegName;
887}
888
889static void printOperand(const MCOperand &MCOp, const MCAsmInfo *MAI,
890 raw_ostream &OS) {
891 if (MCOp.isReg()) {
892 if (!MCOp.getReg())
893 OS << '0';
894 else
895 printFormattedRegName(MAI, MCOp.getReg(), OS);
896 } else if (MCOp.isImm())
897 OS << MCOp.getImm();
898 else if (MCOp.isExpr())
899 MCOp.getExpr()->print(OS, MAI);
900 else
901 llvm_unreachable("Invalid operand");
902}
903
904static void printAddress(const MCAsmInfo *MAI, unsigned Base,
905 const MCOperand &DispMO, unsigned Index,
906 raw_ostream &OS) {
907 printOperand(DispMO, MAI, OS);
908 if (Base || Index) {
909 OS << '(';
910 if (Index) {
912 if (Base)
913 OS << ',';
914 }
915 if (Base)
917 OS << ')';
918 }
919}
920
922 const char *ExtraCode,
923 raw_ostream &OS) {
925 const MachineOperand &MO = MI->getOperand(OpNo);
926 MCOperand MCOp;
927 if (ExtraCode) {
928 if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&
929 SystemZ::GR128BitRegClass.contains(MO.getReg()))
930 MCOp =
931 MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));
932 else
933 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
934 } else {
936 MCOp = Lower.lowerOperand(MO);
937 }
938 printOperand(MCOp, MAI, OS);
939 return false;
940}
941
943 unsigned OpNo,
944 const char *ExtraCode,
945 raw_ostream &OS) {
946 printAddress(MAI, MI->getOperand(OpNo).getReg(),
947 MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()),
948 MI->getOperand(OpNo + 2).getReg(), OS);
949 return false;
950}
951
953 auto TT = OutContext.getTargetTriple();
954 if (TT.isOSzOS()) {
955 emitADASection();
956 }
957 emitAttributes(M);
958}
959
960void SystemZAsmPrinter::emitADASection() {
961 OutStreamer->pushSection();
962
963 const unsigned PointerSize = getDataLayout().getPointerSize();
964 OutStreamer->switchSection(getObjFileLowering().getADASection());
965
966 unsigned EmittedBytes = 0;
967 for (auto &Entry : ADATable.getTable()) {
968 const MCSymbol *Sym;
969 unsigned SlotKind;
970 std::tie(Sym, SlotKind) = Entry.first;
971 unsigned Offset = Entry.second;
972 assert(Offset == EmittedBytes && "Offset not as expected");
973 (void)EmittedBytes;
974#define EMIT_COMMENT(Str) \
975 OutStreamer->AddComment(Twine("Offset ") \
976 .concat(utostr(Offset)) \
977 .concat(" " Str " ") \
978 .concat(Sym->getName()));
979 switch (SlotKind) {
981 // Language Environment DLL logic requires function descriptors, for
982 // imported functions, that are placed in the ADA to be 8 byte aligned.
983 EMIT_COMMENT("function descriptor of");
984 OutStreamer->emitValue(
987 OutContext),
988 PointerSize);
989 OutStreamer->emitValue(
992 OutContext),
993 PointerSize);
994 EmittedBytes += PointerSize * 2;
995 break;
997 EMIT_COMMENT("pointer to data symbol");
998 OutStreamer->emitValue(
1001 OutContext),
1002 PointerSize);
1003 EmittedBytes += PointerSize;
1004 break;
1007 Twine(Sym->getName()).concat("@indirect"));
1008 OutStreamer->emitAssignment(Alias,
1010 OutStreamer->emitSymbolAttribute(Alias, MCSA_IndirectSymbol);
1011
1012 EMIT_COMMENT("pointer to function descriptor");
1013 OutStreamer->emitValue(
1016 OutContext),
1017 PointerSize);
1018 EmittedBytes += PointerSize;
1019 break;
1020 }
1021 default:
1022 llvm_unreachable("Unexpected slot kind");
1023 }
1024#undef EMIT_COMMENT
1025 }
1026 OutStreamer->popSection();
1027}
1028
1030 if (TM.getTargetTriple().isOSzOS()) {
1031 // Emit symbol for the end of function if the z/OS target streamer
1032 // is used. This is needed to calculate the size of the function.
1033 MCSymbol *FnEndSym = createTempSymbol("func_end");
1034 OutStreamer->emitLabel(FnEndSym);
1035
1036 OutStreamer->pushSection();
1037 OutStreamer->switchSection(getObjFileLowering().getPPA1Section());
1038 emitPPA1(FnEndSym);
1039 OutStreamer->popSection();
1040
1041 CurrentFnPPA1Sym = nullptr;
1042 CurrentFnEPMarkerSym = nullptr;
1043 }
1044}
1045
1046static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
1047 bool StackProtector, bool FPRMask, bool VRMask,
1048 bool HasName) {
1049 enum class PPA1Flag1 : uint8_t {
1050 DSA64Bit = (0x80 >> 0),
1051 VarArg = (0x80 >> 7),
1053 };
1054 enum class PPA1Flag2 : uint8_t {
1055 ExternalProcedure = (0x80 >> 0),
1056 STACKPROTECTOR = (0x80 >> 3),
1057 LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure)
1058 };
1059 enum class PPA1Flag3 : uint8_t {
1060 FPRMask = (0x80 >> 2),
1062 };
1063 enum class PPA1Flag4 : uint8_t {
1064 EPMOffsetPresent = (0x80 >> 0),
1065 VRMask = (0x80 >> 2),
1066 ProcedureNamePresent = (0x80 >> 7),
1067 LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent)
1068 };
1069
1070 // Declare optional section flags that can be modified.
1071 auto Flags1 = PPA1Flag1(0);
1072 auto Flags2 = PPA1Flag2::ExternalProcedure;
1073 auto Flags3 = PPA1Flag3(0);
1074 auto Flags4 = PPA1Flag4::EPMOffsetPresent;
1075
1076 Flags1 |= PPA1Flag1::DSA64Bit;
1077
1078 if (VarArg)
1079 Flags1 |= PPA1Flag1::VarArg;
1080
1081 if (StackProtector)
1082 Flags2 |= PPA1Flag2::STACKPROTECTOR;
1083
1084 // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in.
1085 if (FPRMask)
1086 Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag.
1087
1088 if (VRMask)
1089 Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag.
1090
1091 if (HasName)
1092 Flags4 |= PPA1Flag4::ProcedureNamePresent; // Add optional name block.
1093
1094 OutStreamer->AddComment("PPA1 Flags 1");
1095 if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit)
1096 OutStreamer->AddComment(" Bit 0: 1 = 64-bit DSA");
1097 else
1098 OutStreamer->AddComment(" Bit 0: 0 = 32-bit DSA");
1099 if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg)
1100 OutStreamer->AddComment(" Bit 7: 1 = Vararg function");
1101 OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1.
1102
1103 OutStreamer->AddComment("PPA1 Flags 2");
1104 if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure)
1105 OutStreamer->AddComment(" Bit 0: 1 = External procedure");
1106 if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR)
1107 OutStreamer->AddComment(" Bit 3: 1 = STACKPROTECT is enabled");
1108 else
1109 OutStreamer->AddComment(" Bit 3: 0 = STACKPROTECT is not enabled");
1110 OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2.
1111
1112 OutStreamer->AddComment("PPA1 Flags 3");
1113 if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask)
1114 OutStreamer->AddComment(" Bit 2: 1 = FP Reg Mask is in optional area");
1115 OutStreamer->emitInt8(
1116 static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections).
1117
1118 OutStreamer->AddComment("PPA1 Flags 4");
1119 if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask)
1120 OutStreamer->AddComment(" Bit 2: 1 = Vector Reg Mask is in optional area");
1121 if ((Flags4 & PPA1Flag4::ProcedureNamePresent) ==
1122 PPA1Flag4::ProcedureNamePresent)
1123 OutStreamer->AddComment(" Bit 7: 1 = Name Length and Name");
1124 OutStreamer->emitInt8(static_cast<uint8_t>(
1125 Flags4)); // Flags 4 (optional sections, always emit these).
1126}
1127
1128static void emitPPA1Name(std::unique_ptr<MCStreamer> &OutStreamer,
1129 StringRef OutName) {
1130 size_t NameSize = OutName.size();
1131 uint16_t OutSize;
1132 if (NameSize < UINT16_MAX) {
1133 OutSize = static_cast<uint16_t>(NameSize);
1134 } else {
1135 OutName = OutName.substr(0, UINT16_MAX);
1136 OutSize = UINT16_MAX;
1137 }
1138 // Emit padding to ensure that the next optional field word-aligned.
1139 uint8_t ExtraZeros = 4 - ((2 + OutSize) % 4);
1140
1141 SmallString<512> OutnameConv;
1142 ConverterEBCDIC::convertToEBCDIC(OutName, OutnameConv);
1143 OutName = OutnameConv.str();
1144
1145 OutStreamer->AddComment("Length of Name");
1146 OutStreamer->emitInt16(OutSize);
1147 OutStreamer->AddComment("Name of Function");
1148 OutStreamer->emitBytes(OutName);
1149 OutStreamer->emitZeros(ExtraZeros);
1150}
1151
1152void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
1154 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
1155 const auto TargetHasVector = Subtarget.hasVector();
1156
1157 const SystemZMachineFunctionInfo *ZFI =
1159 const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>(
1160 Subtarget.getFrameLowering());
1161 const MachineFrameInfo &MFFrame = MF->getFrameInfo();
1162
1163 // Get saved GPR/FPR/VPR masks.
1164 const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
1165 uint16_t SavedGPRMask = 0;
1166 uint16_t SavedFPRMask = 0;
1167 uint8_t SavedVRMask = 0;
1168 int64_t OffsetFPR = 0;
1169 int64_t OffsetVR = 0;
1170 const int64_t TopOfStack =
1171 MFFrame.getOffsetAdjustment() + MFFrame.getStackSize();
1172
1173 // Loop over the spilled registers. The CalleeSavedInfo can't be used because
1174 // it does not contain all spilled registers.
1175 for (unsigned I = ZFI->getSpillGPRRegs().LowGPR,
1176 E = ZFI->getSpillGPRRegs().HighGPR;
1177 I && E && I <= E; ++I) {
1178 unsigned V = TRI->getEncodingValue((Register)I);
1179 assert(V < 16 && "GPR index out of range");
1180 SavedGPRMask |= 1 << (15 - V);
1181 }
1182
1183 for (auto &CS : CSI) {
1184 unsigned Reg = CS.getReg();
1185 unsigned I = TRI->getEncodingValue(Reg);
1186
1187 if (SystemZ::FP64BitRegClass.contains(Reg)) {
1188 assert(I < 16 && "FPR index out of range");
1189 SavedFPRMask |= 1 << (15 - I);
1190 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
1191 if (Temp < OffsetFPR)
1192 OffsetFPR = Temp;
1193 } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
1194 assert(I >= 16 && I <= 23 && "VPR index out of range");
1195 unsigned BitNum = I - 16;
1196 SavedVRMask |= 1 << (7 - BitNum);
1197 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
1198 if (Temp < OffsetVR)
1199 OffsetVR = Temp;
1200 }
1201 }
1202
1203 // Adjust the offset.
1204 OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0;
1205 OffsetVR += (OffsetVR < 0) ? TopOfStack : 0;
1206
1207 // Get alloca register.
1208 uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF));
1209 uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0;
1210 assert(AllocaReg < 16 && "Can't have alloca register larger than 15");
1211 (void)AllocaReg;
1212
1213 // Build FPR save area offset.
1214 uint32_t FrameAndFPROffset = 0;
1215 if (SavedFPRMask) {
1216 uint64_t FPRSaveAreaOffset = OffsetFPR;
1217 assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range");
1218
1219 FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
1220 FrameAndFPROffset |= FrameReg << 28; // Put into top 4 bits.
1221 }
1222
1223 // Build VR save area offset.
1224 uint32_t FrameAndVROffset = 0;
1225 if (TargetHasVector && SavedVRMask) {
1226 uint64_t VRSaveAreaOffset = OffsetVR;
1227 assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range");
1228
1229 FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
1230 FrameAndVROffset |= FrameReg << 28; // Put into top 4 bits.
1231 }
1232
1233 // Emit PPA1 section.
1234 OutStreamer->AddComment("PPA1");
1235 OutStreamer->emitLabel(CurrentFnPPA1Sym);
1236 OutStreamer->AddComment("Version");
1237 OutStreamer->emitInt8(0x02); // Version.
1238 OutStreamer->AddComment("LE Signature X'CE'");
1239 OutStreamer->emitInt8(0xCE); // CEL signature.
1240 OutStreamer->AddComment("Saved GPR Mask");
1241 OutStreamer->emitInt16(SavedGPRMask);
1242
1243 bool HasName =
1244 MF->getFunction().hasName() && MF->getFunction().getName().size() > 0;
1245
1247 MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,
1248 TargetHasVector && SavedVRMask != 0, HasName);
1249
1250 OutStreamer->AddComment("Length/4 of Parms");
1251 OutStreamer->emitInt16(
1252 static_cast<uint16_t>(ZFI->getSizeOfFnParams() / 4)); // Parms/4.
1253 OutStreamer->AddComment("Length of Code");
1254 OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4);
1255
1256 // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).
1257 if (SavedFPRMask) {
1258 OutStreamer->AddComment("FPR mask");
1259 OutStreamer->emitInt16(SavedFPRMask);
1260 OutStreamer->AddComment("AR mask");
1261 OutStreamer->emitInt16(0); // AR Mask, unused currently.
1262 OutStreamer->AddComment("FPR Save Area Locator");
1263 OutStreamer->AddComment(Twine(" Bit 0-3: Register R")
1264 .concat(utostr(FrameAndFPROffset >> 28))
1265 .str());
1266 OutStreamer->AddComment(Twine(" Bit 4-31: Offset ")
1267 .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF))
1268 .str());
1269 OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with
1270 // register to add value to
1271 // (alloca reg).
1272 }
1273
1274 // Emit saved VR mask to VR save area.
1275 if (TargetHasVector && SavedVRMask) {
1276 OutStreamer->AddComment("VR mask");
1277 OutStreamer->emitInt8(SavedVRMask);
1278 OutStreamer->emitInt8(0); // Reserved.
1279 OutStreamer->emitInt16(0); // Also reserved.
1280 OutStreamer->AddComment("VR Save Area Locator");
1281 OutStreamer->AddComment(Twine(" Bit 0-3: Register R")
1282 .concat(utostr(FrameAndVROffset >> 28))
1283 .str());
1284 OutStreamer->AddComment(Twine(" Bit 4-31: Offset ")
1285 .concat(utostr(FrameAndVROffset & 0x0FFFFFFF))
1286 .str());
1287 OutStreamer->emitInt32(FrameAndVROffset);
1288 }
1289
1290 // Emit name length and name optional section (0x01 of flags 4)
1291 if (HasName)
1293
1294 // Emit offset to entry point optional section (0x80 of flags 4).
1295 OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym,
1296 4);
1297}
1298
1300 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
1301
1302 if (Subtarget.getTargetTriple().isOSzOS()) {
1303 MCContext &OutContext = OutStreamer->getContext();
1304
1305 // Save information for later use.
1306 std::string N(MF->getFunction().hasName()
1307 ? Twine(MF->getFunction().getName()).concat("_").str()
1308 : "");
1309
1310 CurrentFnEPMarkerSym =
1311 OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true);
1312 CurrentFnPPA1Sym =
1313 OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true);
1314
1315 // EntryPoint Marker
1316 const MachineFrameInfo &MFFrame = MF->getFrameInfo();
1317 bool IsUsingAlloca = MFFrame.hasVarSizedObjects();
1318 uint32_t DSASize = MFFrame.getStackSize();
1319 bool IsLeaf = DSASize == 0 && MFFrame.getCalleeSavedInfo().empty();
1320
1321 // Set Flags
1322 uint8_t Flags = 0;
1323 if (IsLeaf)
1324 Flags |= 0x08;
1325 if (IsUsingAlloca)
1326 Flags |= 0x04;
1327
1328 // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.
1329 uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5
1330 DSAAndFlags |= Flags;
1331
1332 // Emit entry point marker section.
1333 OutStreamer->AddComment("XPLINK Routine Layout Entry");
1334 OutStreamer->emitLabel(CurrentFnEPMarkerSym);
1335 OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
1336 OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
1337 OutStreamer->AddComment("Mark Type C'1'");
1338 OutStreamer->emitInt8(0xF1); // Mark Type.
1339 OutStreamer->AddComment("Offset to PPA1");
1340 OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym,
1341 4);
1342 if (OutStreamer->isVerboseAsm()) {
1343 OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
1344 OutStreamer->AddComment("Entry Flags");
1345 if (Flags & 0x08)
1346 OutStreamer->AddComment(" Bit 1: 1 = Leaf function");
1347 else
1348 OutStreamer->AddComment(" Bit 1: 0 = Non-leaf function");
1349 if (Flags & 0x04)
1350 OutStreamer->AddComment(" Bit 2: 1 = Uses alloca");
1351 else
1352 OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca");
1353 }
1354 OutStreamer->emitInt32(DSAAndFlags);
1355 }
1356
1358}
1359
1360// Force static initialization.
1363}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock & MBB
static MCSymbolRefExpr::VariantKind getModifierVariantKind(ARMCP::ARMCPModifier Modifier)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_EXTERNAL_VISIBILITY
Definition: Compiler.h:135
This file provides utility functions for converting between EBCDIC-1047 and UTF-8.
std::string Name
uint64_t Size
Symbol * Sym
Definition: ELF_riscv.cpp:468
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define RegName(no)
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
LLVMContext & Context
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
static bool printOperand(raw_ostream &OS, const SelectionDAG *G, const SDValue Value)
This file contains some functions that are useful when dealing with strings.
static void emitPPA1Name(std::unique_ptr< MCStreamer > &OutStreamer, StringRef OutName)
#define LOWER_LOW(NAME)
static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI, unsigned Opcode)
#define EMIT_COMMENT(Str)
static const MCSymbolRefExpr * getGlobalOffsetTable(MCContext &Context)
#define LOWER_HIGH(NAME)
static void printFormattedRegName(const MCAsmInfo *MAI, unsigned RegNo, raw_ostream &OS)
static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode)
static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter()
static void emitPPA1Flags(std::unique_ptr< MCStreamer > &OutStreamer, bool VarArg, bool StackProtector, bool FPRMask, bool VRMask, bool HasName)
static void printAddress(const MCAsmInfo *MAI, unsigned Base, const MCOperand &DispMO, unsigned Index, raw_ostream &OS)
static const MCSymbolRefExpr * getTLSGetOffset(MCContext &Context)
static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode)
static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, unsigned NumBytes, const MCSubtargetInfo &STI)
static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode)
static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:470
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
Definition: AsmPrinter.cpp:381
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:671
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
Definition: AsmPrinter.cpp:401
TargetMachine & TM
Target machine description.
Definition: AsmPrinter.h:88
const MCAsmInfo * MAI
Target Asm Printer information.
Definition: AsmPrinter.h:91
MachineFunction * MF
The current machine function.
Definition: AsmPrinter.h:103
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition: AsmPrinter.h:95
MCSymbol * createTempSymbol(const Twine &Name) const
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition: AsmPrinter.h:100
StackMaps SM
Definition: AsmPrinter.h:211
const DataLayout & getDataLayout() const
Return information about data layout.
Definition: AsmPrinter.cpp:385
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
Definition: AsmPrinter.cpp:396
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
This class represents an Operation in the Expression.
TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
Definition: DataLayout.h:504
unsigned getPointerSize(unsigned AS=0) const
Layout pointer size in bytes, rounded up to a whole number of bytes.
Definition: DataLayout.cpp:748
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
Definition: Function.h:189
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.cpp:645
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition: MCAsmInfo.h:56
unsigned getAssemblerDialect() const
Definition: MCAsmInfo.h:686
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:528
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
Context object for machine code objects.
Definition: MCContext.h:76
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:322
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
Definition: MCContext.h:565
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:201
const Triple & getTargetTriple() const
Definition: MCContext.h:434
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
void print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens=false) const
Definition: MCExpr.cpp:41
MCInstBuilder & addReg(unsigned Reg)
Add a new register operand.
Definition: MCInstBuilder.h:31
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:37
MCInstBuilder & addExpr(const MCExpr *Val)
Add a new MCExpr operand.
Definition: MCInstBuilder.h:55
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
void setOpcode(unsigned Op)
Definition: MCInst.h:197
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
int64_t getImm() const
Definition: MCInst.h:80
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
bool isImm() const
Definition: MCInst.h:62
unsigned getReg() const
Returns the register number.
Definition: MCInst.h:69
bool isReg() const
Definition: MCInst.h:61
const MCExpr * getExpr() const
Definition: MCInst.h:114
bool isExpr() const
Definition: MCInst.h:65
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Streaming machine code generation interface.
Definition: MCStreamer.h:212
virtual void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI)
Emit the given Instruction into the current section.
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Definition: MCStreamer.cpp:424
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:192
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:389
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
Abstract base class for all machine specific constantpool value subclasses.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
int getOffsetAdjustment() const
Return the correction for frame offsets.
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
bool hasStackProtectorIndex() const
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Representation of each machine instruction.
Definition: MachineInstr.h:68
const MachineFunction * getMF() const
Return the function that contains the basic block that this instruction belongs to.
MachineOperand class - Representation of each machine instruction operand.
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
MachineInstr * getParent()
getParent - Return the instruction that this operand belongs to.
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
@ MO_GlobalAddress
Address of a global value.
@ MO_ExternalSymbol
Name of external global symbol.
const TargetRegisterInfo * getTargetRegisterInfo() const
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
MI-level patchpoint operands.
Definition: StackMaps.h:76
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition: SmallString.h:26
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:261
void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
Definition: StackMaps.cpp:554
void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
Definition: StackMaps.cpp:544
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:575
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override
void emitFunctionBodyEnd() override
Targets can override this to emit stuff after the last basic block in the function.
void emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
void emitFunctionEntryLabel() override
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
void emitEndOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the end of their file...
A SystemZ-specific constant pool value.
static const char * getRegisterName(MCRegister Reg)
static const SystemZMCExpr * create(VariantKind Kind, const MCExpr *Expr, MCContext &Ctx)
const SystemZInstrInfo * getInstrInfo() const override
const TargetFrameLowering * getFrameLowering() const override
std::pair< MCInst, const MCSubtargetInfo * > MCInstSTIPair
const Triple & getTargetTriple() const
const MCSubtargetInfo * getMCSubtargetInfo() const
MCSymbol * getSymbol(const GlobalValue *GV) const
const MCRegisterInfo * getMCRegisterInfo() const
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
bool isOSzOS() const
Definition: Triple.h:515
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
std::string str() const
Return the twine contents as a std::string.
Definition: Twine.cpp:17
Twine concat(const Twine &Suffix) const
Definition: Twine.h:525
static Twine utohexstr(const uint64_t &Val)
Definition: Twine.h:416
bool hasName() const
Definition: Value.h:261
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:309
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Key
PAL metadata keys.
std::error_code convertToEBCDIC(StringRef Source, SmallVectorImpl< char > &Result)
@ SHT_PROGBITS
Definition: ELF.h:1000
@ SHF_ALLOC
Definition: ELF.h:1089
unsigned getRegAsGR32(unsigned Reg)
const unsigned GR64Regs[16]
unsigned getRegAsGRH32(unsigned Reg)
unsigned getRegAsVR128(unsigned Reg)
unsigned getRegAsGR64(unsigned Reg)
Reg
All possible values of the reg field in the ModR/M byte.
constexpr size_t NameSize
Definition: XCOFF.h:29
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Target & getTheSystemZTarget()
@ Offset
Definition: DWP.cpp:440
@ Length
Definition: DWP.cpp:440
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&... Ranges)
Concatenated range across two or more ranges.
Definition: STLExtras.h:1186
@ MCSA_IndirectSymbol
.indirect_symbol (MachO)
Definition: MCDirectives.h:35
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...