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