Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
35266 views
1
//===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Streams SystemZ assembly language and associated data, in the form of
10
// MCInsts and MCExprs respectively.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "SystemZAsmPrinter.h"
15
#include "MCTargetDesc/SystemZInstPrinter.h"
16
#include "MCTargetDesc/SystemZMCExpr.h"
17
#include "SystemZConstantPoolValue.h"
18
#include "SystemZMCInstLower.h"
19
#include "TargetInfo/SystemZTargetInfo.h"
20
#include "llvm/ADT/StringExtras.h"
21
#include "llvm/BinaryFormat/ELF.h"
22
#include "llvm/CodeGen/MachineModuleInfoImpls.h"
23
#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
24
#include "llvm/IR/Mangler.h"
25
#include "llvm/IR/Module.h"
26
#include "llvm/MC/MCExpr.h"
27
#include "llvm/MC/MCInstBuilder.h"
28
#include "llvm/MC/MCSectionELF.h"
29
#include "llvm/MC/MCStreamer.h"
30
#include "llvm/MC/TargetRegistry.h"
31
#include "llvm/Support/Chrono.h"
32
#include "llvm/Support/ConvertEBCDIC.h"
33
#include "llvm/Support/FormatProviders.h"
34
#include "llvm/Support/FormatVariadic.h"
35
36
using namespace llvm;
37
38
// Return an RI instruction like MI with opcode Opcode, but with the
39
// GR64 register operands turned into GR32s.
40
static 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.
54
static 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.
68
static 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
78
static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
79
StringRef Name = "__tls_get_offset";
80
return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
81
MCSymbolRefExpr::VK_PLT,
82
Context);
83
}
84
85
static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {
86
StringRef Name = "_GLOBAL_OFFSET_TABLE_";
87
return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
88
MCSymbolRefExpr::VK_None,
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.
96
static 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.
121
static 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.
131
static 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.
145
void SystemZAsmPrinter::emitCallInformation(CallType CT) {
146
EmitToStreamer(*OutStreamer,
147
MCInstBuilder(SystemZ::BCRAsm)
148
.addImm(0)
149
.addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
150
}
151
152
uint32_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.
161
uint32_t Length;
162
switch (SlotKind) {
163
case SystemZII::MO_ADA_DIRECT_FUNC_DESC:
164
Length = 2 * PointerSize;
165
break;
166
default:
167
Length = PointerSize;
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
178
uint32_t
179
SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MachineOperand MO) {
180
MCSymbol *Sym;
181
if (MO.getType() == MachineOperand::MO_GlobalAddress) {
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
196
void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
197
SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(),
198
getSubtargetInfo().getFeatureBits());
199
200
SystemZMCInstLower Lower(MF->getContext(), *this);
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:
304
EmitToStreamer(*OutStreamer,
305
MCInstBuilder(SystemZ::BRASL)
306
.addReg(SystemZ::R7D)
307
.addExpr(Lower.getExpr(MI->getOperand(0),
308
MCSymbolRefExpr::VK_PLT)));
309
emitCallInformation(CallType::BRASL7);
310
return;
311
312
case SystemZ::CallBASR_XPLINK64:
313
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
314
.addReg(SystemZ::R7D)
315
.addReg(MI->getOperand(0).getReg()));
316
emitCallInformation(CallType::BASR76);
317
return;
318
319
case SystemZ::CallBASR_STACKEXT:
320
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
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.
345
EmitToStreamer(
346
*OutStreamer,
347
MCInstBuilder(SystemZ::LLILF).addReg(TargetReg).addImm(Disp));
348
} else
349
EmitToStreamer(
350
*OutStreamer,
351
MCInstBuilder(SystemZ::ALGFI).addReg(TargetReg).addImm(Disp));
352
Disp = 0;
353
Op = Op0;
354
}
355
EmitToStreamer(*OutStreamer, MCInstBuilder(Op)
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)
474
.addExpr(getTLSGetOffset(MF->getContext()))
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)
481
.addExpr(getTLSGetOffset(MF->getContext()))
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())
488
.addExpr(getGlobalOffsetTable(MF->getContext()));
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: {
626
MCSymbol *DotSym = OutContext.createTempSymbol();
627
OutStreamer->emitLabel(DotSym);
628
629
const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
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: {
639
MCSymbol *DotSym = OutContext.createTempSymbol();
640
OutStreamer->emitLabel(DotSym);
641
642
const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
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);
675
SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
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();
682
const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
683
EmitToStreamer(
684
*OutStreamer,
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.
698
static 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
725
void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
726
SystemZMCInstLower &Lower) {
727
MCContext &Ctx = MF->getContext();
728
if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
729
MCSymbol *DotSym = OutContext.createTempSymbol();
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")) {
739
EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
740
return;
741
}
742
743
MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
744
const MCSymbolRefExpr *Op =
745
MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx);
746
OutStreamer->emitInstruction(
747
MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
748
getSubtargetInfo());
749
}
750
751
void 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();
766
MachineBasicBlock::const_iterator MII(MI);
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,
782
getSubtargetInfo());
783
}
784
785
// Lower a patchpoint of the form:
786
// [<def>], <id>, <numBytes>, <target>, <numArgs>
787
void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
788
SystemZMCInstLower &Lower) {
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
810
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
811
.addReg(ScratchReg)
812
.addImm(CallTarget & 0xFFFFFFFF));
813
EncodedBytes += 6;
814
if (CallTarget >> 32) {
815
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
816
.addReg(ScratchReg)
817
.addImm(CallTarget >> 32));
818
EncodedBytes += 6;
819
}
820
821
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
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);
828
EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
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,
842
getSubtargetInfo());
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.
848
void 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.
858
static MCSymbolRefExpr::VariantKind
859
getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
860
switch (Modifier) {
861
case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
862
case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
863
case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
864
case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
865
}
866
llvm_unreachable("Invalid SystemCPModifier!");
867
}
868
869
void SystemZAsmPrinter::emitMachineConstantPoolValue(
870
MachineConstantPoolValue *MCPV) {
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
882
static 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
893
static 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
900
static 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
912
static 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) {
919
printFormattedRegName(MAI, Index, OS);
920
if (Base)
921
OS << ',';
922
}
923
if (Base)
924
printFormattedRegName(MAI, Base, OS);
925
OS << ')';
926
}
927
}
928
929
bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
930
const char *ExtraCode,
931
raw_ostream &OS) {
932
const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
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 {
943
SystemZMCInstLower Lower(MF->getContext(), *this);
944
MCOp = Lower.lowerOperand(MO);
945
}
946
printOperand(MCOp, MAI, OS);
947
return false;
948
}
949
950
bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
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
975
void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
976
auto TT = OutContext.getTargetTriple();
977
if (TT.isOSzOS()) {
978
emitADASection();
979
emitIDRLSection(M);
980
}
981
emitAttributes(M);
982
}
983
984
void 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) {
1004
case SystemZII::MO_ADA_DIRECT_FUNC_DESC:
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(
1009
SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_RCon,
1010
MCSymbolRefExpr::create(Sym, OutContext),
1011
OutContext),
1012
PointerSize);
1013
OutStreamer->emitValue(
1014
SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_VCon,
1015
MCSymbolRefExpr::create(Sym, OutContext),
1016
OutContext),
1017
PointerSize);
1018
EmittedBytes += PointerSize * 2;
1019
break;
1020
case SystemZII::MO_ADA_DATA_SYMBOL_ADDR:
1021
EMIT_COMMENT("pointer to data symbol");
1022
OutStreamer->emitValue(
1023
SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_None,
1024
MCSymbolRefExpr::create(Sym, OutContext),
1025
OutContext),
1026
PointerSize);
1027
EmittedBytes += PointerSize;
1028
break;
1029
case SystemZII::MO_ADA_INDIRECT_FUNC_DESC: {
1030
MCSymbol *Alias = OutContext.createTempSymbol(
1031
Twine(Sym->getName()).concat("@indirect"));
1032
OutStreamer->emitAssignment(Alias,
1033
MCSymbolRefExpr::create(Sym, OutContext));
1034
OutStreamer->emitSymbolAttribute(Alias, MCSA_IndirectSymbol);
1035
1036
EMIT_COMMENT("pointer to function descriptor");
1037
OutStreamer->emitValue(
1038
SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_VCon,
1039
MCSymbolRefExpr::create(Alias, OutContext),
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
1053
static 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
1062
static uint32_t getProductVersion(Module &M) {
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
1069
static uint32_t getProductRelease(Module &M) {
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
1076
static uint32_t getProductPatch(Module &M) {
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
1083
static 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
1093
void 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
1104
SmallString<IDRLDataLength + 1> TempStr;
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");
1109
SmallString<IDRLDataLength> Data;
1110
ConverterEBCDIC::convertToEBCDIC(TempStr, Data);
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
1119
void SystemZAsmPrinter::emitFunctionBodyEnd() {
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
1136
static 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),
1142
LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit)
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),
1151
LLVM_MARK_AS_BITMASK_ENUM(FPRMask)
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
1224
static 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
1248
void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
1249
assert(PPA2Sym != nullptr && "PPA2 Symbol not defined");
1250
1251
const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
1252
const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
1253
const auto TargetHasVector = Subtarget.hasVector();
1254
1255
const SystemZMachineFunctionInfo *ZFI =
1256
MF->getInfo<SystemZMachineFunctionInfo>();
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
1348
emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(),
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>(
1396
MF->getFunction().getPersonalityFn()->stripPointerCasts());
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");
1409
MCSymbol *GCCEH = MF->getContext().getOrCreateSymbol(
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)
1417
emitPPA1Name(OutStreamer, MF->getFunction().getName());
1418
1419
// Emit offset to entry point optional section (0x80 of flags 4).
1420
OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym,
1421
4);
1422
}
1423
1424
void SystemZAsmPrinter::emitStartOfAsmFile(Module &M) {
1425
if (TM.getTargetTriple().isOSzOS())
1426
emitPPA2(M);
1427
AsmPrinter::emitStartOfAsmFile(M);
1428
}
1429
1430
void 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
1452
raw_svector_ostream ostr(Version);
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);
1461
ConverterEBCDIC::convertToEBCDIC(Version, VersionStr);
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") {
1515
report_fatal_error(
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
1545
void SystemZAsmPrinter::emitFunctionEntryLabel() {
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
1603
AsmPrinter::emitFunctionEntryLabel();
1604
}
1605
1606
// Force static initialization.
1607
extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() {
1608
RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
1609
}
1610
1611