LLVM 19.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"
30#include "llvm/Support/Chrono.h"
34
35using namespace llvm;
36
37// Return an RI instruction like MI with opcode Opcode, but with the
38// GR64 register operands turned into GR32s.
39static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
40 if (MI->isCompare())
41 return MCInstBuilder(Opcode)
42 .addReg(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.
53static 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.
67static 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
77static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
78 StringRef Name = "__tls_get_offset";
79 return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
81 Context);
82}
83
85 StringRef Name = "_GLOBAL_OFFSET_TABLE_";
86 return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
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.
95static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI,
96 unsigned Opcode) {
97 if (MI->memoperands_empty())
98 return;
99
100 Align Alignment = Align(16);
101 for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(),
102 EE = MI->memoperands_end(); MMOI != EE; ++MMOI)
103 if ((*MMOI)->getAlign() < Alignment)
104 Alignment = (*MMOI)->getAlign();
105
106 unsigned AlignmentHint = 0;
107 if (Alignment >= Align(16))
108 AlignmentHint = 4;
109 else if (Alignment >= Align(8))
110 AlignmentHint = 3;
111 if (AlignmentHint == 0)
112 return;
113
114 LoweredMI.setOpcode(Opcode);
115 LoweredMI.addOperand(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.
120static 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.
130static 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.
144void SystemZAsmPrinter::emitCallInformation(CallType CT) {
146 MCInstBuilder(SystemZ::BCRAsm)
147 .addImm(0)
148 .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
149}
150
151uint32_t SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MCSymbol *Sym,
152 unsigned SlotKind) {
153 auto Key = std::make_pair(Sym, SlotKind);
154 auto It = Displacements.find(Key);
155
156 if (It != Displacements.end())
157 return (*It).second;
158
159 // Determine length of descriptor.
161 switch (SlotKind) {
163 Length = 2 * PointerSize;
164 break;
165 default:
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
178SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MachineOperand MO) {
179 MCSymbol *Sym;
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
196 SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(),
197 getSubtargetInfo().getFeatureBits());
198
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:
304 MCInstBuilder(SystemZ::BRASL)
305 .addReg(SystemZ::R7D)
306 .addExpr(Lower.getExpr(MI->getOperand(0),
308 emitCallInformation(CallType::BRASL7);
309 return;
310
311 case SystemZ::CallBASR_XPLINK64:
313 .addReg(SystemZ::R7D)
314 .addReg(MI->getOperand(0).getReg()));
315 emitCallInformation(CallType::BASR76);
316 return;
317
318 case SystemZ::CallBASR_STACKEXT:
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.
346 MCInstBuilder(SystemZ::LLILF).addReg(TargetReg).addImm(Disp));
347 } else
350 MCInstBuilder(SystemZ::ALGFI).addReg(TargetReg).addImm(Disp));
351 Disp = 0;
352 Op = Op0;
353 }
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)
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)
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())
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: {
626 OutStreamer->emitLabel(DotSym);
627
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: {
639 OutStreamer->emitLabel(DotSym);
640
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);
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();
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.
697static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
698 unsigned NumBytes, const MCSubtargetInfo &STI) {
699 if (NumBytes < 2) {
700 llvm_unreachable("Zero nops?");
701 return 0;
702 }
703 else if (NumBytes < 4) {
704 OutStreamer.emitInstruction(
705 MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
706 return 2;
707 }
708 else if (NumBytes < 6) {
709 OutStreamer.emitInstruction(
710 MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
711 STI);
712 return 4;
713 }
714 else {
715 MCSymbol *DotSym = OutContext.createTempSymbol();
716 const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
717 OutStreamer.emitLabel(DotSym);
718 OutStreamer.emitInstruction(
719 MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
720 return 6;
721 }
722}
723
724void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
726 MCContext &Ctx = MF->getContext();
727 if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
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")) {
739 return;
740 }
741
742 MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
743 const MCSymbolRefExpr *Op =
745 OutStreamer->emitInstruction(
746 MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
748}
749
750void 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();
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,
782}
783
784// Lower a patchpoint of the form:
785// [<def>], <id>, <numBytes>, <target>, <numArgs>
786void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
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
810 .addReg(ScratchReg)
811 .addImm(CallTarget & 0xFFFFFFFF));
812 EncodedBytes += 6;
813 if (CallTarget >> 32) {
815 .addReg(ScratchReg)
816 .addImm(CallTarget >> 32));
817 EncodedBytes += 6;
818 }
819
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);
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,
842}
843
844// The *alignment* of 128-bit vector types is different between the software
845// and hardware vector ABIs. If the there is an externally visible use of a
846// vector type in the module it should be annotated with an attribute.
847void SystemZAsmPrinter::emitAttributes(Module &M) {
848 if (M.getModuleFlag("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.
859 switch (Modifier) {
864 }
865 llvm_unreachable("Invalid SystemCPModifier!");
866}
867
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
881static 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
892static void printReg(unsigned Reg, const MCAsmInfo *MAI, raw_ostream &OS) {
893 if (!Reg)
894 OS << '0';
895 else
896 printFormattedRegName(MAI, Reg, OS);
897}
898
899static void printOperand(const MCOperand &MCOp, const MCAsmInfo *MAI,
900 raw_ostream &OS) {
901 if (MCOp.isReg())
902 printReg(MCOp.getReg(), MAI, OS);
903 else if (MCOp.isImm())
904 OS << MCOp.getImm();
905 else if (MCOp.isExpr())
906 MCOp.getExpr()->print(OS, MAI);
907 else
908 llvm_unreachable("Invalid operand");
909}
910
911static void printAddress(const MCAsmInfo *MAI, unsigned Base,
912 const MCOperand &DispMO, unsigned Index,
913 raw_ostream &OS) {
914 printOperand(DispMO, MAI, OS);
915 if (Base || Index) {
916 OS << '(';
917 if (Index) {
919 if (Base)
920 OS << ',';
921 }
922 if (Base)
924 OS << ')';
925 }
926}
927
929 const char *ExtraCode,
930 raw_ostream &OS) {
932 const MachineOperand &MO = MI->getOperand(OpNo);
933 MCOperand MCOp;
934 if (ExtraCode) {
935 if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&
936 SystemZ::GR128BitRegClass.contains(MO.getReg()))
937 MCOp =
938 MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));
939 else
940 return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
941 } else {
943 MCOp = Lower.lowerOperand(MO);
944 }
945 printOperand(MCOp, MAI, OS);
946 return false;
947}
948
950 unsigned OpNo,
951 const char *ExtraCode,
952 raw_ostream &OS) {
953 if (ExtraCode && ExtraCode[0] && !ExtraCode[1]) {
954 switch (ExtraCode[0]) {
955 case 'A':
956 // Unlike EmitMachineNode(), EmitSpecialNode(INLINEASM) does not call
957 // setMemRefs(), so MI->memoperands() is empty and the alignment
958 // information is not available.
959 return false;
960 case 'O':
961 OS << MI->getOperand(OpNo + 1).getImm();
962 return false;
963 case 'R':
964 ::printReg(MI->getOperand(OpNo).getReg(), MAI, OS);
965 return false;
966 }
967 }
968 printAddress(MAI, MI->getOperand(OpNo).getReg(),
969 MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()),
970 MI->getOperand(OpNo + 2).getReg(), OS);
971 return false;
972}
973
975 auto TT = OutContext.getTargetTriple();
976 if (TT.isOSzOS()) {
977 emitADASection();
978 emitIDRLSection(M);
979 }
980 emitAttributes(M);
981}
982
983void SystemZAsmPrinter::emitADASection() {
984 OutStreamer->pushSection();
985
986 const unsigned PointerSize = getDataLayout().getPointerSize();
987 OutStreamer->switchSection(getObjFileLowering().getADASection());
988
989 unsigned EmittedBytes = 0;
990 for (auto &Entry : ADATable.getTable()) {
991 const MCSymbol *Sym;
992 unsigned SlotKind;
993 std::tie(Sym, SlotKind) = Entry.first;
994 unsigned Offset = Entry.second;
995 assert(Offset == EmittedBytes && "Offset not as expected");
996 (void)EmittedBytes;
997#define EMIT_COMMENT(Str) \
998 OutStreamer->AddComment(Twine("Offset ") \
999 .concat(utostr(Offset)) \
1000 .concat(" " Str " ") \
1001 .concat(Sym->getName()));
1002 switch (SlotKind) {
1004 // Language Environment DLL logic requires function descriptors, for
1005 // imported functions, that are placed in the ADA to be 8 byte aligned.
1006 EMIT_COMMENT("function descriptor of");
1007 OutStreamer->emitValue(
1010 OutContext),
1011 PointerSize);
1012 OutStreamer->emitValue(
1015 OutContext),
1016 PointerSize);
1017 EmittedBytes += PointerSize * 2;
1018 break;
1020 EMIT_COMMENT("pointer to data symbol");
1021 OutStreamer->emitValue(
1024 OutContext),
1025 PointerSize);
1026 EmittedBytes += PointerSize;
1027 break;
1030 Twine(Sym->getName()).concat("@indirect"));
1031 OutStreamer->emitAssignment(Alias,
1033 OutStreamer->emitSymbolAttribute(Alias, MCSA_IndirectSymbol);
1034
1035 EMIT_COMMENT("pointer to function descriptor");
1036 OutStreamer->emitValue(
1039 OutContext),
1040 PointerSize);
1041 EmittedBytes += PointerSize;
1042 break;
1043 }
1044 default:
1045 llvm_unreachable("Unexpected slot kind");
1046 }
1047#undef EMIT_COMMENT
1048 }
1049 OutStreamer->popSection();
1050}
1051
1052static std::string getProductID(Module &M) {
1053 std::string ProductID;
1054 if (auto *MD = M.getModuleFlag("zos_product_id"))
1055 ProductID = cast<MDString>(MD)->getString().str();
1056 if (ProductID.empty())
1057 ProductID = "LLVM";
1058 return ProductID;
1059}
1060
1062 if (auto *VersionVal = mdconst::extract_or_null<ConstantInt>(
1063 M.getModuleFlag("zos_product_major_version")))
1064 return VersionVal->getZExtValue();
1065 return LLVM_VERSION_MAJOR;
1066}
1067
1069 if (auto *ReleaseVal = mdconst::extract_or_null<ConstantInt>(
1070 M.getModuleFlag("zos_product_minor_version")))
1071 return ReleaseVal->getZExtValue();
1072 return LLVM_VERSION_MINOR;
1073}
1074
1076 if (auto *PatchVal = mdconst::extract_or_null<ConstantInt>(
1077 M.getModuleFlag("zos_product_patchlevel")))
1078 return PatchVal->getZExtValue();
1079 return LLVM_VERSION_PATCH;
1080}
1081
1082static time_t getTranslationTime(Module &M) {
1083 std::time_t Time = 0;
1084 if (auto *Val = mdconst::extract_or_null<ConstantInt>(
1085 M.getModuleFlag("zos_translation_time"))) {
1086 long SecondsSinceEpoch = Val->getSExtValue();
1087 Time = static_cast<time_t>(SecondsSinceEpoch);
1088 }
1089 return Time;
1090}
1091
1092void SystemZAsmPrinter::emitIDRLSection(Module &M) {
1093 OutStreamer->pushSection();
1094 OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
1095 constexpr unsigned IDRLDataLength = 30;
1096 std::time_t Time = getTranslationTime(M);
1097
1098 uint32_t ProductVersion = getProductVersion(M);
1099 uint32_t ProductRelease = getProductRelease(M);
1100
1101 std::string ProductID = getProductID(M);
1102
1104 raw_svector_ostream O(TempStr);
1105 O << formatv("{0,-10}{1,0-2:d}{2,0-2:d}{3:%Y%m%d%H%M%S}{4,0-2}",
1106 ProductID.substr(0, 10).c_str(), ProductVersion, ProductRelease,
1107 llvm::sys::toUtcTime(Time), "0");
1110
1111 OutStreamer->emitInt8(0); // Reserved.
1112 OutStreamer->emitInt8(3); // Format.
1113 OutStreamer->emitInt16(IDRLDataLength); // Length.
1114 OutStreamer->emitBytes(Data.str());
1115 OutStreamer->popSection();
1116}
1117
1119 if (TM.getTargetTriple().isOSzOS()) {
1120 // Emit symbol for the end of function if the z/OS target streamer
1121 // is used. This is needed to calculate the size of the function.
1122 MCSymbol *FnEndSym = createTempSymbol("func_end");
1123 OutStreamer->emitLabel(FnEndSym);
1124
1125 OutStreamer->pushSection();
1126 OutStreamer->switchSection(getObjFileLowering().getPPA1Section());
1127 emitPPA1(FnEndSym);
1128 OutStreamer->popSection();
1129
1130 CurrentFnPPA1Sym = nullptr;
1131 CurrentFnEPMarkerSym = nullptr;
1132 }
1133}
1134
1135static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
1136 bool StackProtector, bool FPRMask, bool VRMask,
1137 bool EHBlock, bool HasName) {
1138 enum class PPA1Flag1 : uint8_t {
1139 DSA64Bit = (0x80 >> 0),
1140 VarArg = (0x80 >> 7),
1142 };
1143 enum class PPA1Flag2 : uint8_t {
1144 ExternalProcedure = (0x80 >> 0),
1145 STACKPROTECTOR = (0x80 >> 3),
1146 LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure)
1147 };
1148 enum class PPA1Flag3 : uint8_t {
1149 FPRMask = (0x80 >> 2),
1151 };
1152 enum class PPA1Flag4 : uint8_t {
1153 EPMOffsetPresent = (0x80 >> 0),
1154 VRMask = (0x80 >> 2),
1155 EHBlock = (0x80 >> 3),
1156 ProcedureNamePresent = (0x80 >> 7),
1157 LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent)
1158 };
1159
1160 // Declare optional section flags that can be modified.
1161 auto Flags1 = PPA1Flag1(0);
1162 auto Flags2 = PPA1Flag2::ExternalProcedure;
1163 auto Flags3 = PPA1Flag3(0);
1164 auto Flags4 = PPA1Flag4::EPMOffsetPresent;
1165
1166 Flags1 |= PPA1Flag1::DSA64Bit;
1167
1168 if (VarArg)
1169 Flags1 |= PPA1Flag1::VarArg;
1170
1171 if (StackProtector)
1172 Flags2 |= PPA1Flag2::STACKPROTECTOR;
1173
1174 // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in.
1175 if (FPRMask)
1176 Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag.
1177
1178 if (VRMask)
1179 Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag.
1180
1181 if (EHBlock)
1182 Flags4 |= PPA1Flag4::EHBlock; // Add optional EH block.
1183
1184 if (HasName)
1185 Flags4 |= PPA1Flag4::ProcedureNamePresent; // Add optional name block.
1186
1187 OutStreamer->AddComment("PPA1 Flags 1");
1188 if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit)
1189 OutStreamer->AddComment(" Bit 0: 1 = 64-bit DSA");
1190 else
1191 OutStreamer->AddComment(" Bit 0: 0 = 32-bit DSA");
1192 if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg)
1193 OutStreamer->AddComment(" Bit 7: 1 = Vararg function");
1194 OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1.
1195
1196 OutStreamer->AddComment("PPA1 Flags 2");
1197 if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure)
1198 OutStreamer->AddComment(" Bit 0: 1 = External procedure");
1199 if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR)
1200 OutStreamer->AddComment(" Bit 3: 1 = STACKPROTECT is enabled");
1201 else
1202 OutStreamer->AddComment(" Bit 3: 0 = STACKPROTECT is not enabled");
1203 OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2.
1204
1205 OutStreamer->AddComment("PPA1 Flags 3");
1206 if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask)
1207 OutStreamer->AddComment(" Bit 2: 1 = FP Reg Mask is in optional area");
1208 OutStreamer->emitInt8(
1209 static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections).
1210
1211 OutStreamer->AddComment("PPA1 Flags 4");
1212 if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask)
1213 OutStreamer->AddComment(" Bit 2: 1 = Vector Reg Mask is in optional area");
1214 if ((Flags4 & PPA1Flag4::EHBlock) == PPA1Flag4::EHBlock)
1215 OutStreamer->AddComment(" Bit 3: 1 = C++ EH block");
1216 if ((Flags4 & PPA1Flag4::ProcedureNamePresent) ==
1217 PPA1Flag4::ProcedureNamePresent)
1218 OutStreamer->AddComment(" Bit 7: 1 = Name Length and Name");
1219 OutStreamer->emitInt8(static_cast<uint8_t>(
1220 Flags4)); // Flags 4 (optional sections, always emit these).
1221}
1222
1223static void emitPPA1Name(std::unique_ptr<MCStreamer> &OutStreamer,
1224 StringRef OutName) {
1225 size_t NameSize = OutName.size();
1226 uint16_t OutSize;
1227 if (NameSize < UINT16_MAX) {
1228 OutSize = static_cast<uint16_t>(NameSize);
1229 } else {
1230 OutName = OutName.substr(0, UINT16_MAX);
1231 OutSize = UINT16_MAX;
1232 }
1233 // Emit padding to ensure that the next optional field word-aligned.
1234 uint8_t ExtraZeros = 4 - ((2 + OutSize) % 4);
1235
1236 SmallString<512> OutnameConv;
1237 ConverterEBCDIC::convertToEBCDIC(OutName, OutnameConv);
1238 OutName = OutnameConv.str();
1239
1240 OutStreamer->AddComment("Length of Name");
1241 OutStreamer->emitInt16(OutSize);
1242 OutStreamer->AddComment("Name of Function");
1243 OutStreamer->emitBytes(OutName);
1244 OutStreamer->emitZeros(ExtraZeros);
1245}
1246
1247void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
1248 assert(PPA2Sym != nullptr && "PPA2 Symbol not defined");
1249
1251 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
1252 const auto TargetHasVector = Subtarget.hasVector();
1253
1254 const SystemZMachineFunctionInfo *ZFI =
1256 const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>(
1257 Subtarget.getFrameLowering());
1258 const MachineFrameInfo &MFFrame = MF->getFrameInfo();
1259
1260 // Get saved GPR/FPR/VPR masks.
1261 const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
1262 uint16_t SavedGPRMask = 0;
1263 uint16_t SavedFPRMask = 0;
1264 uint8_t SavedVRMask = 0;
1265 int64_t OffsetFPR = 0;
1266 int64_t OffsetVR = 0;
1267 const int64_t TopOfStack =
1268 MFFrame.getOffsetAdjustment() + MFFrame.getStackSize();
1269
1270 // Loop over the spilled registers. The CalleeSavedInfo can't be used because
1271 // it does not contain all spilled registers.
1272 for (unsigned I = ZFI->getSpillGPRRegs().LowGPR,
1273 E = ZFI->getSpillGPRRegs().HighGPR;
1274 I && E && I <= E; ++I) {
1275 unsigned V = TRI->getEncodingValue((Register)I);
1276 assert(V < 16 && "GPR index out of range");
1277 SavedGPRMask |= 1 << (15 - V);
1278 }
1279
1280 for (auto &CS : CSI) {
1281 unsigned Reg = CS.getReg();
1282 unsigned I = TRI->getEncodingValue(Reg);
1283
1284 if (SystemZ::FP64BitRegClass.contains(Reg)) {
1285 assert(I < 16 && "FPR index out of range");
1286 SavedFPRMask |= 1 << (15 - I);
1287 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
1288 if (Temp < OffsetFPR)
1289 OffsetFPR = Temp;
1290 } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
1291 assert(I >= 16 && I <= 23 && "VPR index out of range");
1292 unsigned BitNum = I - 16;
1293 SavedVRMask |= 1 << (7 - BitNum);
1294 int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
1295 if (Temp < OffsetVR)
1296 OffsetVR = Temp;
1297 }
1298 }
1299
1300 // Adjust the offset.
1301 OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0;
1302 OffsetVR += (OffsetVR < 0) ? TopOfStack : 0;
1303
1304 // Get alloca register.
1305 uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF));
1306 uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0;
1307 assert(AllocaReg < 16 && "Can't have alloca register larger than 15");
1308 (void)AllocaReg;
1309
1310 // Build FPR save area offset.
1311 uint32_t FrameAndFPROffset = 0;
1312 if (SavedFPRMask) {
1313 uint64_t FPRSaveAreaOffset = OffsetFPR;
1314 assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range");
1315
1316 FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
1317 FrameAndFPROffset |= FrameReg << 28; // Put into top 4 bits.
1318 }
1319
1320 // Build VR save area offset.
1321 uint32_t FrameAndVROffset = 0;
1322 if (TargetHasVector && SavedVRMask) {
1323 uint64_t VRSaveAreaOffset = OffsetVR;
1324 assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range");
1325
1326 FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
1327 FrameAndVROffset |= FrameReg << 28; // Put into top 4 bits.
1328 }
1329
1330 // Emit PPA1 section.
1331 OutStreamer->AddComment("PPA1");
1332 OutStreamer->emitLabel(CurrentFnPPA1Sym);
1333 OutStreamer->AddComment("Version");
1334 OutStreamer->emitInt8(0x02); // Version.
1335 OutStreamer->AddComment("LE Signature X'CE'");
1336 OutStreamer->emitInt8(0xCE); // CEL signature.
1337 OutStreamer->AddComment("Saved GPR Mask");
1338 OutStreamer->emitInt16(SavedGPRMask);
1339 OutStreamer->AddComment("Offset to PPA2");
1340 OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CurrentFnPPA1Sym, 4);
1341
1342 bool NeedEmitEHBlock = !MF->getLandingPads().empty();
1343
1344 bool HasName =
1345 MF->getFunction().hasName() && MF->getFunction().getName().size() > 0;
1346
1348 MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,
1349 TargetHasVector && SavedVRMask != 0, NeedEmitEHBlock, HasName);
1350
1351 OutStreamer->AddComment("Length/4 of Parms");
1352 OutStreamer->emitInt16(
1353 static_cast<uint16_t>(ZFI->getSizeOfFnParams() / 4)); // Parms/4.
1354 OutStreamer->AddComment("Length of Code");
1355 OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4);
1356
1357 // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).
1358 if (SavedFPRMask) {
1359 OutStreamer->AddComment("FPR mask");
1360 OutStreamer->emitInt16(SavedFPRMask);
1361 OutStreamer->AddComment("AR mask");
1362 OutStreamer->emitInt16(0); // AR Mask, unused currently.
1363 OutStreamer->AddComment("FPR Save Area Locator");
1364 OutStreamer->AddComment(Twine(" Bit 0-3: Register R")
1365 .concat(utostr(FrameAndFPROffset >> 28))
1366 .str());
1367 OutStreamer->AddComment(Twine(" Bit 4-31: Offset ")
1368 .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF))
1369 .str());
1370 OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with
1371 // register to add value to
1372 // (alloca reg).
1373 }
1374
1375 // Emit saved VR mask to VR save area.
1376 if (TargetHasVector && SavedVRMask) {
1377 OutStreamer->AddComment("VR mask");
1378 OutStreamer->emitInt8(SavedVRMask);
1379 OutStreamer->emitInt8(0); // Reserved.
1380 OutStreamer->emitInt16(0); // Also reserved.
1381 OutStreamer->AddComment("VR Save Area Locator");
1382 OutStreamer->AddComment(Twine(" Bit 0-3: Register R")
1383 .concat(utostr(FrameAndVROffset >> 28))
1384 .str());
1385 OutStreamer->AddComment(Twine(" Bit 4-31: Offset ")
1386 .concat(utostr(FrameAndVROffset & 0x0FFFFFFF))
1387 .str());
1388 OutStreamer->emitInt32(FrameAndVROffset);
1389 }
1390
1391 // Emit C++ EH information block
1392 const Function *Per = nullptr;
1393 if (NeedEmitEHBlock) {
1394 Per = dyn_cast<Function>(
1396 MCSymbol *PersonalityRoutine =
1397 Per ? MF->getTarget().getSymbol(Per) : nullptr;
1398 assert(PersonalityRoutine && "Missing personality routine");
1399
1400 OutStreamer->AddComment("Version");
1401 OutStreamer->emitInt32(1);
1402 OutStreamer->AddComment("Flags");
1403 OutStreamer->emitInt32(0); // LSDA field is a WAS offset
1404 OutStreamer->AddComment("Personality routine");
1405 OutStreamer->emitInt64(ADATable.insert(
1406 PersonalityRoutine, SystemZII::MO_ADA_INDIRECT_FUNC_DESC));
1407 OutStreamer->AddComment("LSDA location");
1409 Twine("GCC_except_table") + Twine(MF->getFunctionNumber()));
1410 OutStreamer->emitInt64(
1411 ADATable.insert(GCCEH, SystemZII::MO_ADA_DATA_SYMBOL_ADDR));
1412 }
1413
1414 // Emit name length and name optional section (0x01 of flags 4)
1415 if (HasName)
1417
1418 // Emit offset to entry point optional section (0x80 of flags 4).
1419 OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym,
1420 4);
1421}
1422
1424 if (TM.getTargetTriple().isOSzOS())
1425 emitPPA2(M);
1427}
1428
1429void SystemZAsmPrinter::emitPPA2(Module &M) {
1430 OutStreamer->pushSection();
1431 OutStreamer->switchSection(getObjFileLowering().getPPA2Section());
1432 MCContext &OutContext = OutStreamer->getContext();
1433 // Make CELQSTRT symbol.
1434 const char *StartSymbolName = "CELQSTRT";
1435 MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);
1436
1437 // Create symbol and assign to class field for use in PPA1.
1438 PPA2Sym = OutContext.createTempSymbol("PPA2", false);
1439 MCSymbol *DateVersionSym = OutContext.createTempSymbol("DVS", false);
1440
1441 std::time_t Time = getTranslationTime(M);
1442 SmallString<15> CompilationTime; // 14 + null
1443 raw_svector_ostream O(CompilationTime);
1444 O << formatv("{0:%Y%m%d%H%M%S}", llvm::sys::toUtcTime(Time));
1445
1446 uint32_t ProductVersion = getProductVersion(M),
1447 ProductRelease = getProductRelease(M),
1448 ProductPatch = getProductPatch(M);
1449
1450 SmallString<7> Version; // 6 + null
1451 raw_svector_ostream ostr(Version);
1452 ostr << formatv("{0,0-2:d}{1,0-2:d}{2,0-2:d}", ProductVersion, ProductRelease,
1453 ProductPatch);
1454
1455 // Drop 0 during conversion.
1456 SmallString<sizeof(CompilationTime) - 1> CompilationTimeStr;
1457 SmallString<sizeof(Version) - 1> VersionStr;
1458
1459 ConverterEBCDIC::convertToEBCDIC(CompilationTime, CompilationTimeStr);
1460 ConverterEBCDIC::convertToEBCDIC(Version, VersionStr);
1461
1462 enum class PPA2MemberId : uint8_t {
1463 // See z/OS Language Environment Vendor Interfaces v2r5, p.23, for
1464 // complete list. Only the C runtime is supported by this backend.
1465 LE_C_Runtime = 3,
1466 };
1467 enum class PPA2MemberSubId : uint8_t {
1468 // List of languages using the LE C runtime implementation.
1469 C = 0x00,
1470 CXX = 0x01,
1471 Swift = 0x03,
1472 Go = 0x60,
1473 LLVMBasedLang = 0xe7,
1474 };
1475 // PPA2 Flags
1476 enum class PPA2Flags : uint8_t {
1477 CompileForBinaryFloatingPoint = 0x80,
1478 CompiledWithXPLink = 0x01,
1479 CompiledUnitASCII = 0x04,
1480 HasServiceInfo = 0x20,
1481 };
1482
1483 PPA2MemberSubId MemberSubId = PPA2MemberSubId::LLVMBasedLang;
1484 if (auto *MD = M.getModuleFlag("zos_cu_language")) {
1485 StringRef Language = cast<MDString>(MD)->getString();
1486 MemberSubId = StringSwitch<PPA2MemberSubId>(Language)
1487 .Case("C", PPA2MemberSubId::C)
1488 .Case("C++", PPA2MemberSubId::CXX)
1489 .Case("Swift", PPA2MemberSubId::Swift)
1490 .Case("Go", PPA2MemberSubId::Go)
1491 .Default(PPA2MemberSubId::LLVMBasedLang);
1492 }
1493
1494 // Emit PPA2 section.
1495 OutStreamer->emitLabel(PPA2Sym);
1496 OutStreamer->emitInt8(static_cast<uint8_t>(PPA2MemberId::LE_C_Runtime));
1497 OutStreamer->emitInt8(static_cast<uint8_t>(MemberSubId));
1498 OutStreamer->emitInt8(0x22); // Member defined, c370_plist+c370_env
1499 OutStreamer->emitInt8(0x04); // Control level 4 (XPLink)
1500 OutStreamer->emitAbsoluteSymbolDiff(CELQSTRT, PPA2Sym, 4);
1501 OutStreamer->emitInt32(0x00000000);
1502 OutStreamer->emitAbsoluteSymbolDiff(DateVersionSym, PPA2Sym, 4);
1503 OutStreamer->emitInt32(
1504 0x00000000); // Offset to main entry point, always 0 (so says TR).
1505 uint8_t Flgs = static_cast<uint8_t>(PPA2Flags::CompileForBinaryFloatingPoint);
1506 Flgs |= static_cast<uint8_t>(PPA2Flags::CompiledWithXPLink);
1507
1508 if (auto *MD = M.getModuleFlag("zos_le_char_mode")) {
1509 const StringRef &CharMode = cast<MDString>(MD)->getString();
1510 if (CharMode == "ascii") {
1511 Flgs |= static_cast<uint8_t>(
1512 PPA2Flags::CompiledUnitASCII); // Setting bit for ASCII char. mode.
1513 } else if (CharMode != "ebcdic") {
1515 "Only ascii or ebcdic are valid values for zos_le_char_mode "
1516 "metadata");
1517 }
1518 }
1519
1520 OutStreamer->emitInt8(Flgs);
1521 OutStreamer->emitInt8(0x00); // Reserved.
1522 // No MD5 signature before timestamp.
1523 // No FLOAT(AFP(VOLATILE)).
1524 // Remaining 5 flag bits reserved.
1525 OutStreamer->emitInt16(0x0000); // 16 Reserved flag bits.
1526
1527 // Emit date and version section.
1528 OutStreamer->emitLabel(DateVersionSym);
1529 OutStreamer->emitBytes(CompilationTimeStr.str());
1530 OutStreamer->emitBytes(VersionStr.str());
1531
1532 OutStreamer->emitInt16(0x0000); // Service level string length.
1533
1534 // The binder requires that the offset to the PPA2 be emitted in a different,
1535 // specially-named section.
1536 OutStreamer->switchSection(getObjFileLowering().getPPA2ListSection());
1537 // Emit 8 byte alignment.
1538 // Emit pointer to PPA2 label.
1539 OutStreamer->AddComment("A(PPA2-CELQSTRT)");
1540 OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CELQSTRT, 8);
1541 OutStreamer->popSection();
1542}
1543
1545 const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
1546
1547 if (Subtarget.getTargetTriple().isOSzOS()) {
1548 MCContext &OutContext = OutStreamer->getContext();
1549
1550 // Save information for later use.
1551 std::string N(MF->getFunction().hasName()
1552 ? Twine(MF->getFunction().getName()).concat("_").str()
1553 : "");
1554
1555 CurrentFnEPMarkerSym =
1556 OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true);
1557 CurrentFnPPA1Sym =
1558 OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true);
1559
1560 // EntryPoint Marker
1561 const MachineFrameInfo &MFFrame = MF->getFrameInfo();
1562 bool IsUsingAlloca = MFFrame.hasVarSizedObjects();
1563 uint32_t DSASize = MFFrame.getStackSize();
1564 bool IsLeaf = DSASize == 0 && MFFrame.getCalleeSavedInfo().empty();
1565
1566 // Set Flags.
1567 uint8_t Flags = 0;
1568 if (IsLeaf)
1569 Flags |= 0x08;
1570 if (IsUsingAlloca)
1571 Flags |= 0x04;
1572
1573 // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.
1574 uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5
1575 DSAAndFlags |= Flags;
1576
1577 // Emit entry point marker section.
1578 OutStreamer->AddComment("XPLINK Routine Layout Entry");
1579 OutStreamer->emitLabel(CurrentFnEPMarkerSym);
1580 OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
1581 OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
1582 OutStreamer->AddComment("Mark Type C'1'");
1583 OutStreamer->emitInt8(0xF1); // Mark Type.
1584 OutStreamer->AddComment("Offset to PPA1");
1585 OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym,
1586 4);
1587 if (OutStreamer->isVerboseAsm()) {
1588 OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
1589 OutStreamer->AddComment("Entry Flags");
1590 if (Flags & 0x08)
1591 OutStreamer->AddComment(" Bit 1: 1 = Leaf function");
1592 else
1593 OutStreamer->AddComment(" Bit 1: 0 = Non-leaf function");
1594 if (Flags & 0x04)
1595 OutStreamer->AddComment(" Bit 2: 1 = Uses alloca");
1596 else
1597 OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca");
1598 }
1599 OutStreamer->emitInt32(DSAAndFlags);
1600 }
1601
1603}
1604
1605// Force static initialization.
1608}
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock & MBB
static MCSymbolRefExpr::VariantKind getModifierVariantKind(ARMCP::ARMCPModifier Modifier)
#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:479
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 uint32_t getProductVersion(Module &M)
static std::string getProductID(Module &M)
static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode)
static void emitPPA1Flags(std::unique_ptr< MCStreamer > &OutStreamer, bool VarArg, bool StackProtector, bool FPRMask, bool VRMask, bool EHBlock, bool HasName)
LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter()
static void printAddress(const MCAsmInfo *MAI, unsigned Base, const MCOperand &DispMO, unsigned Index, raw_ostream &OS)
static time_t getTranslationTime(Module &M)
static const MCSymbolRefExpr * getTLSGetOffset(MCContext &Context)
static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode)
static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, unsigned NumBytes, const MCSubtargetInfo &STI)
static uint32_t getProductRelease(Module &M)
static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode)
static uint32_t getProductPatch(Module &M)
static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode)
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
Definition: AsmPrinter.cpp:398
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:700
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
Definition: AsmPrinter.cpp:418
TargetMachine & TM
Target machine description.
Definition: AsmPrinter.h:87
const MCAsmInfo * MAI
Target Asm Printer information.
Definition: AsmPrinter.h:90
MachineFunction * MF
The current machine function.
Definition: AsmPrinter.h:102
virtual void emitStartOfAsmFile(Module &)
This virtual method can be overridden by targets that want to emit something at the start of their fi...
Definition: AsmPrinter.h:543
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition: AsmPrinter.h:94
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:99
StackMaps SM
Definition: AsmPrinter.h:210
const DataLayout & getDataLayout() const
Return information about data layout.
Definition: AsmPrinter.cpp:402
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:413
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.
const Constant * stripPointerCasts() const
Definition: Constant.h:213
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:750
Constant * getPersonalityFn() const
Get the personality function associated with this function.
Definition: Function.cpp:1882
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
Definition: Function.h:213
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.cpp:677
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:682
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:536
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:321
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
Definition: MCContext.h:567
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:200
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:37
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:43
MCInstBuilder & addExpr(const MCExpr *Val)
Add a new MCExpr operand.
Definition: MCInstBuilder.h:61
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:397
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:40
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.
unsigned getFunctionNumber() const
getFunctionNumber - Return a unique ID for the current function.
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
const std::vector< LandingPadInfo > & getLandingPads() const
Return a reference to the landing pad info for the current function.
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:69
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:254
void recordPatchPoint(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a patchpoint instruction.
Definition: StackMaps.cpp:548
void recordStackMap(const MCSymbol &L, const MachineInstr &MI)
Generate a stackmap record for a stackmap instruction.
Definition: StackMaps.cpp:538
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:567
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:44
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:69
R Default(T Value)
Definition: StringSwitch.h:182
void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override
void emitFunctionBodyEnd() override
Targets can override this to emit stuff after the last basic block in the function.
void emitStartOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the start of their fi...
void emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
void emitFunctionEntryLabel() override
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
void emitEndOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the end of their file...
A SystemZ-specific constant pool value.
static const char * getRegisterName(MCRegister Reg)
static const 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:539
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
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:690
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Language[]
Key for Kernel::Metadata::mLanguage.
Key
PAL metadata keys.
@ Swift
Calling convention for Swift.
Definition: CallingConv.h:69
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
std::error_code convertToEBCDIC(StringRef Source, SmallVectorImpl< char > &Result)
@ SHF_ALLOC
Definition: ELF.h:1157
@ SHT_PROGBITS
Definition: ELF.h:1063
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
UtcTime< std::chrono::seconds > toUtcTime(std::time_t T)
Convert a std::time_t to a UtcTime.
Definition: Chrono.h:44
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
Target & getTheSystemZTarget()
@ Offset
Definition: DWP.cpp:456
@ Length
Definition: DWP.cpp:456
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:156
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&... Ranges)
Concatenated range across two or more ranges.
Definition: STLExtras.h:1185
Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.
@ MCSA_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,...