xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Streams SystemZ assembly language and associated data, in the form of
100b57cec5SDimitry Andric // MCInsts and MCExprs respectively.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "SystemZAsmPrinter.h"
150b57cec5SDimitry Andric #include "MCTargetDesc/SystemZInstPrinter.h"
1606c3fb27SDimitry Andric #include "MCTargetDesc/SystemZMCExpr.h"
170b57cec5SDimitry Andric #include "SystemZConstantPoolValue.h"
180b57cec5SDimitry Andric #include "SystemZMCInstLower.h"
190b57cec5SDimitry Andric #include "TargetInfo/SystemZTargetInfo.h"
2006c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h"
21480093f4SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h"
230b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
240b57cec5SDimitry Andric #include "llvm/IR/Mangler.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCInstBuilder.h"
27480093f4SDimitry Andric #include "llvm/MC/MCSectionELF.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
29349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
30*5f757f3fSDimitry Andric #include "llvm/Support/Chrono.h"
31*5f757f3fSDimitry Andric #include "llvm/Support/ConvertEBCDIC.h"
32*5f757f3fSDimitry Andric #include "llvm/Support/FormatProviders.h"
33*5f757f3fSDimitry Andric #include "llvm/Support/FormatVariadic.h"
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric using namespace llvm;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the
380b57cec5SDimitry Andric // GR64 register operands turned into GR32s.
390b57cec5SDimitry Andric static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
400b57cec5SDimitry Andric   if (MI->isCompare())
410b57cec5SDimitry Andric     return MCInstBuilder(Opcode)
420b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
430b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm());
440b57cec5SDimitry Andric   else
450b57cec5SDimitry Andric     return MCInstBuilder(Opcode)
460b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
470b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))
480b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm());
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the
520b57cec5SDimitry Andric // GR64 register operands turned into GRH32s.
530b57cec5SDimitry Andric static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {
540b57cec5SDimitry Andric   if (MI->isCompare())
550b57cec5SDimitry Andric     return MCInstBuilder(Opcode)
560b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
570b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm());
580b57cec5SDimitry Andric   else
590b57cec5SDimitry Andric     return MCInstBuilder(Opcode)
600b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
610b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg()))
620b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm());
630b57cec5SDimitry Andric }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the
660b57cec5SDimitry Andric // R2 register turned into a GR64.
670b57cec5SDimitry Andric static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
680b57cec5SDimitry Andric   return MCInstBuilder(Opcode)
690b57cec5SDimitry Andric     .addReg(MI->getOperand(0).getReg())
700b57cec5SDimitry Andric     .addReg(MI->getOperand(1).getReg())
710b57cec5SDimitry Andric     .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))
720b57cec5SDimitry Andric     .addImm(MI->getOperand(3).getImm())
730b57cec5SDimitry Andric     .addImm(MI->getOperand(4).getImm())
740b57cec5SDimitry Andric     .addImm(MI->getOperand(5).getImm());
750b57cec5SDimitry Andric }
760b57cec5SDimitry Andric 
770b57cec5SDimitry Andric static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
780b57cec5SDimitry Andric   StringRef Name = "__tls_get_offset";
790b57cec5SDimitry Andric   return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
800b57cec5SDimitry Andric                                  MCSymbolRefExpr::VK_PLT,
810b57cec5SDimitry Andric                                  Context);
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {
850b57cec5SDimitry Andric   StringRef Name = "_GLOBAL_OFFSET_TABLE_";
860b57cec5SDimitry Andric   return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
870b57cec5SDimitry Andric                                  MCSymbolRefExpr::VK_None,
880b57cec5SDimitry Andric                                  Context);
890b57cec5SDimitry Andric }
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric // MI is an instruction that accepts an optional alignment hint,
920b57cec5SDimitry Andric // and which was already lowered to LoweredMI.  If the alignment
930b57cec5SDimitry Andric // of the original memory operand is known, update LoweredMI to
940b57cec5SDimitry Andric // an instruction with the corresponding hint set.
950b57cec5SDimitry Andric static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI,
960b57cec5SDimitry Andric                                unsigned Opcode) {
9781ad6265SDimitry Andric   if (MI->memoperands_empty())
980b57cec5SDimitry Andric     return;
9981ad6265SDimitry Andric 
10081ad6265SDimitry Andric   Align Alignment = Align(16);
10181ad6265SDimitry Andric   for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(),
10281ad6265SDimitry Andric          EE = MI->memoperands_end(); MMOI != EE; ++MMOI)
10381ad6265SDimitry Andric     if ((*MMOI)->getAlign() < Alignment)
10481ad6265SDimitry Andric       Alignment = (*MMOI)->getAlign();
10581ad6265SDimitry Andric 
1060b57cec5SDimitry Andric   unsigned AlignmentHint = 0;
10781ad6265SDimitry Andric   if (Alignment >= Align(16))
1080b57cec5SDimitry Andric     AlignmentHint = 4;
10981ad6265SDimitry Andric   else if (Alignment >= Align(8))
1100b57cec5SDimitry Andric     AlignmentHint = 3;
1110b57cec5SDimitry Andric   if (AlignmentHint == 0)
1120b57cec5SDimitry Andric     return;
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   LoweredMI.setOpcode(Opcode);
1150b57cec5SDimitry Andric   LoweredMI.addOperand(MCOperand::createImm(AlignmentHint));
1160b57cec5SDimitry Andric }
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric // MI loads the high part of a vector from memory.  Return an instruction
1190b57cec5SDimitry Andric // that uses replicating vector load Opcode to do the same thing.
1200b57cec5SDimitry Andric static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {
1210b57cec5SDimitry Andric   return MCInstBuilder(Opcode)
1220b57cec5SDimitry Andric     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
1230b57cec5SDimitry Andric     .addReg(MI->getOperand(1).getReg())
1240b57cec5SDimitry Andric     .addImm(MI->getOperand(2).getImm())
1250b57cec5SDimitry Andric     .addReg(MI->getOperand(3).getReg());
1260b57cec5SDimitry Andric }
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric // MI stores the high part of a vector to memory.  Return an instruction
1290b57cec5SDimitry Andric // that uses elemental vector store Opcode to do the same thing.
1300b57cec5SDimitry Andric static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
1310b57cec5SDimitry Andric   return MCInstBuilder(Opcode)
1320b57cec5SDimitry Andric     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
1330b57cec5SDimitry Andric     .addReg(MI->getOperand(1).getReg())
1340b57cec5SDimitry Andric     .addImm(MI->getOperand(2).getImm())
1350b57cec5SDimitry Andric     .addReg(MI->getOperand(3).getReg())
1360b57cec5SDimitry Andric     .addImm(0);
1370b57cec5SDimitry Andric }
1380b57cec5SDimitry Andric 
13981ad6265SDimitry Andric // The XPLINK ABI requires that a no-op encoding the call type is emitted after
14081ad6265SDimitry Andric // each call to a subroutine. This information can be used by the called
14181ad6265SDimitry Andric // function to determine its entry point, e.g. for generating a backtrace. The
14281ad6265SDimitry Andric // call type is encoded as a register number in the bcr instruction. See
14381ad6265SDimitry Andric // enumeration CallType for the possible values.
14481ad6265SDimitry Andric void SystemZAsmPrinter::emitCallInformation(CallType CT) {
14581ad6265SDimitry Andric   EmitToStreamer(*OutStreamer,
14681ad6265SDimitry Andric                  MCInstBuilder(SystemZ::BCRAsm)
14781ad6265SDimitry Andric                      .addImm(0)
14881ad6265SDimitry Andric                      .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
14981ad6265SDimitry Andric }
15081ad6265SDimitry Andric 
15106c3fb27SDimitry Andric uint32_t SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MCSymbol *Sym,
15206c3fb27SDimitry Andric                                                             unsigned SlotKind) {
15306c3fb27SDimitry Andric   auto Key = std::make_pair(Sym, SlotKind);
15406c3fb27SDimitry Andric   auto It = Displacements.find(Key);
15506c3fb27SDimitry Andric 
15606c3fb27SDimitry Andric   if (It != Displacements.end())
15706c3fb27SDimitry Andric     return (*It).second;
15806c3fb27SDimitry Andric 
15906c3fb27SDimitry Andric   // Determine length of descriptor.
16006c3fb27SDimitry Andric   uint32_t Length;
16106c3fb27SDimitry Andric   switch (SlotKind) {
16206c3fb27SDimitry Andric   case SystemZII::MO_ADA_DIRECT_FUNC_DESC:
16306c3fb27SDimitry Andric     Length = 2 * PointerSize;
16406c3fb27SDimitry Andric     break;
16506c3fb27SDimitry Andric   default:
16606c3fb27SDimitry Andric     Length = PointerSize;
16706c3fb27SDimitry Andric     break;
16806c3fb27SDimitry Andric   }
16906c3fb27SDimitry Andric 
17006c3fb27SDimitry Andric   uint32_t Displacement = NextDisplacement;
17106c3fb27SDimitry Andric   Displacements[std::make_pair(Sym, SlotKind)] = NextDisplacement;
17206c3fb27SDimitry Andric   NextDisplacement += Length;
17306c3fb27SDimitry Andric 
17406c3fb27SDimitry Andric   return Displacement;
17506c3fb27SDimitry Andric }
17606c3fb27SDimitry Andric 
17706c3fb27SDimitry Andric uint32_t
17806c3fb27SDimitry Andric SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MachineOperand MO) {
17906c3fb27SDimitry Andric   MCSymbol *Sym;
18006c3fb27SDimitry Andric   if (MO.getType() == MachineOperand::MO_GlobalAddress) {
18106c3fb27SDimitry Andric     const GlobalValue *GV = MO.getGlobal();
18206c3fb27SDimitry Andric     Sym = MO.getParent()->getMF()->getTarget().getSymbol(GV);
18306c3fb27SDimitry Andric     assert(Sym && "No symbol");
18406c3fb27SDimitry Andric   } else if (MO.getType() == MachineOperand::MO_ExternalSymbol) {
18506c3fb27SDimitry Andric     const char *SymName = MO.getSymbolName();
18606c3fb27SDimitry Andric     Sym = MO.getParent()->getMF()->getContext().getOrCreateSymbol(SymName);
18706c3fb27SDimitry Andric     assert(Sym && "No symbol");
18806c3fb27SDimitry Andric   } else
18906c3fb27SDimitry Andric     llvm_unreachable("Unexpected operand type");
19006c3fb27SDimitry Andric 
19106c3fb27SDimitry Andric   unsigned ADAslotType = MO.getTargetFlags();
19206c3fb27SDimitry Andric   return insert(Sym, ADAslotType);
19306c3fb27SDimitry Andric }
19406c3fb27SDimitry Andric 
1955ffd83dbSDimitry Andric void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
196753f127fSDimitry Andric   SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(),
197753f127fSDimitry Andric                                           getSubtargetInfo().getFeatureBits());
198753f127fSDimitry Andric 
1990b57cec5SDimitry Andric   SystemZMCInstLower Lower(MF->getContext(), *this);
2000b57cec5SDimitry Andric   MCInst LoweredMI;
2010b57cec5SDimitry Andric   switch (MI->getOpcode()) {
2020b57cec5SDimitry Andric   case SystemZ::Return:
20381ad6265SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BR)
20481ad6265SDimitry Andric       .addReg(SystemZ::R14D);
20581ad6265SDimitry Andric     break;
20681ad6265SDimitry Andric 
20781ad6265SDimitry Andric   case SystemZ::Return_XPLINK:
20881ad6265SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::B)
20981ad6265SDimitry Andric       .addReg(SystemZ::R7D)
21081ad6265SDimitry Andric       .addImm(2)
21181ad6265SDimitry Andric       .addReg(0);
2120b57cec5SDimitry Andric     break;
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   case SystemZ::CondReturn:
2150b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BCR)
2160b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
2170b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2180b57cec5SDimitry Andric       .addReg(SystemZ::R14D);
2190b57cec5SDimitry Andric     break;
2200b57cec5SDimitry Andric 
22181ad6265SDimitry Andric   case SystemZ::CondReturn_XPLINK:
22281ad6265SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BC)
22381ad6265SDimitry Andric       .addImm(MI->getOperand(0).getImm())
22481ad6265SDimitry Andric       .addImm(MI->getOperand(1).getImm())
22581ad6265SDimitry Andric       .addReg(SystemZ::R7D)
22681ad6265SDimitry Andric       .addImm(2)
22781ad6265SDimitry Andric       .addReg(0);
22881ad6265SDimitry Andric     break;
22981ad6265SDimitry Andric 
2300b57cec5SDimitry Andric   case SystemZ::CRBReturn:
2310b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CRB)
2320b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2330b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
2340b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2350b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2360b57cec5SDimitry Andric       .addImm(0);
2370b57cec5SDimitry Andric     break;
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   case SystemZ::CGRBReturn:
2400b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGRB)
2410b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2420b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
2430b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2440b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2450b57cec5SDimitry Andric       .addImm(0);
2460b57cec5SDimitry Andric     break;
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric   case SystemZ::CIBReturn:
2490b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CIB)
2500b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2510b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2520b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2530b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2540b57cec5SDimitry Andric       .addImm(0);
2550b57cec5SDimitry Andric     break;
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric   case SystemZ::CGIBReturn:
2580b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGIB)
2590b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2600b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2610b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2620b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2630b57cec5SDimitry Andric       .addImm(0);
2640b57cec5SDimitry Andric     break;
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   case SystemZ::CLRBReturn:
2670b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLRB)
2680b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2690b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
2700b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2710b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2720b57cec5SDimitry Andric       .addImm(0);
2730b57cec5SDimitry Andric     break;
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric   case SystemZ::CLGRBReturn:
2760b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
2770b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2780b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
2790b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2800b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2810b57cec5SDimitry Andric       .addImm(0);
2820b57cec5SDimitry Andric     break;
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   case SystemZ::CLIBReturn:
2850b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLIB)
2860b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2870b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2880b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2890b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2900b57cec5SDimitry Andric       .addImm(0);
2910b57cec5SDimitry Andric     break;
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric   case SystemZ::CLGIBReturn:
2940b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
2950b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2960b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2970b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2980b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2990b57cec5SDimitry Andric       .addImm(0);
3000b57cec5SDimitry Andric     break;
3010b57cec5SDimitry Andric 
302fe6060f1SDimitry Andric   case SystemZ::CallBRASL_XPLINK64:
303fe6060f1SDimitry Andric     EmitToStreamer(*OutStreamer,
304fe6060f1SDimitry Andric                    MCInstBuilder(SystemZ::BRASL)
305fe6060f1SDimitry Andric                        .addReg(SystemZ::R7D)
306fe6060f1SDimitry Andric                        .addExpr(Lower.getExpr(MI->getOperand(0),
307fe6060f1SDimitry Andric                                               MCSymbolRefExpr::VK_PLT)));
30881ad6265SDimitry Andric     emitCallInformation(CallType::BRASL7);
309fe6060f1SDimitry Andric     return;
310fe6060f1SDimitry Andric 
311fe6060f1SDimitry Andric   case SystemZ::CallBASR_XPLINK64:
312fe6060f1SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
313fe6060f1SDimitry Andric                                      .addReg(SystemZ::R7D)
314fe6060f1SDimitry Andric                                      .addReg(MI->getOperand(0).getReg()));
31581ad6265SDimitry Andric     emitCallInformation(CallType::BASR76);
31681ad6265SDimitry Andric     return;
31781ad6265SDimitry Andric 
31881ad6265SDimitry Andric   case SystemZ::CallBASR_STACKEXT:
31981ad6265SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
32081ad6265SDimitry Andric                                      .addReg(SystemZ::R3D)
32181ad6265SDimitry Andric                                      .addReg(MI->getOperand(0).getReg()));
32281ad6265SDimitry Andric     emitCallInformation(CallType::BASR33);
323fe6060f1SDimitry Andric     return;
324fe6060f1SDimitry Andric 
32506c3fb27SDimitry Andric   case SystemZ::ADA_ENTRY_VALUE:
32606c3fb27SDimitry Andric   case SystemZ::ADA_ENTRY: {
32706c3fb27SDimitry Andric     const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
32806c3fb27SDimitry Andric     const SystemZInstrInfo *TII = Subtarget.getInstrInfo();
32906c3fb27SDimitry Andric     uint32_t Disp = ADATable.insert(MI->getOperand(1));
33006c3fb27SDimitry Andric     Register TargetReg = MI->getOperand(0).getReg();
33106c3fb27SDimitry Andric 
33206c3fb27SDimitry Andric     Register ADAReg = MI->getOperand(2).getReg();
33306c3fb27SDimitry Andric     Disp += MI->getOperand(3).getImm();
33406c3fb27SDimitry Andric     bool LoadAddr = MI->getOpcode() == SystemZ::ADA_ENTRY;
33506c3fb27SDimitry Andric 
33606c3fb27SDimitry Andric     unsigned Op0 = LoadAddr ? SystemZ::LA : SystemZ::LG;
33706c3fb27SDimitry Andric     unsigned Op = TII->getOpcodeForOffset(Op0, Disp);
33806c3fb27SDimitry Andric 
33906c3fb27SDimitry Andric     Register IndexReg = 0;
34006c3fb27SDimitry Andric     if (!Op) {
34106c3fb27SDimitry Andric       if (TargetReg != ADAReg) {
34206c3fb27SDimitry Andric         IndexReg = TargetReg;
34306c3fb27SDimitry Andric         // Use TargetReg to store displacement.
34406c3fb27SDimitry Andric         EmitToStreamer(
34506c3fb27SDimitry Andric             *OutStreamer,
34606c3fb27SDimitry Andric             MCInstBuilder(SystemZ::LLILF).addReg(TargetReg).addImm(Disp));
34706c3fb27SDimitry Andric       } else
34806c3fb27SDimitry Andric         EmitToStreamer(
34906c3fb27SDimitry Andric             *OutStreamer,
35006c3fb27SDimitry Andric             MCInstBuilder(SystemZ::ALGFI).addReg(TargetReg).addImm(Disp));
35106c3fb27SDimitry Andric       Disp = 0;
35206c3fb27SDimitry Andric       Op = Op0;
35306c3fb27SDimitry Andric     }
35406c3fb27SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(Op)
35506c3fb27SDimitry Andric                                      .addReg(TargetReg)
356*5f757f3fSDimitry Andric                                      .addReg(ADAReg)
35706c3fb27SDimitry Andric                                      .addImm(Disp)
358*5f757f3fSDimitry Andric                                      .addReg(IndexReg));
35906c3fb27SDimitry Andric 
36006c3fb27SDimitry Andric     return;
36106c3fb27SDimitry Andric   }
3620b57cec5SDimitry Andric   case SystemZ::CallBRASL:
3630b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRASL)
3640b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
3650b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
3660b57cec5SDimitry Andric     break;
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric   case SystemZ::CallBASR:
3690b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BASR)
3700b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
3710b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg());
3720b57cec5SDimitry Andric     break;
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   case SystemZ::CallJG:
3750b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::JG)
3760b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
3770b57cec5SDimitry Andric     break;
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric   case SystemZ::CallBRCL:
3800b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRCL)
3810b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
3820b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
3830b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT));
3840b57cec5SDimitry Andric     break;
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric   case SystemZ::CallBR:
387e8d8bef9SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BR)
388e8d8bef9SDimitry Andric       .addReg(MI->getOperand(0).getReg());
3890b57cec5SDimitry Andric     break;
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric   case SystemZ::CallBCR:
3920b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BCR)
3930b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
3940b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
395e8d8bef9SDimitry Andric       .addReg(MI->getOperand(2).getReg());
3960b57cec5SDimitry Andric     break;
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   case SystemZ::CRBCall:
3990b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CRB)
4000b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4010b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
4020b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
403e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4040b57cec5SDimitry Andric       .addImm(0);
4050b57cec5SDimitry Andric     break;
4060b57cec5SDimitry Andric 
4070b57cec5SDimitry Andric   case SystemZ::CGRBCall:
4080b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGRB)
4090b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4100b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
4110b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
412e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4130b57cec5SDimitry Andric       .addImm(0);
4140b57cec5SDimitry Andric     break;
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   case SystemZ::CIBCall:
4170b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CIB)
4180b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4190b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
4200b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
421e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4220b57cec5SDimitry Andric       .addImm(0);
4230b57cec5SDimitry Andric     break;
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   case SystemZ::CGIBCall:
4260b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGIB)
4270b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4280b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
4290b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
430e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4310b57cec5SDimitry Andric       .addImm(0);
4320b57cec5SDimitry Andric     break;
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric   case SystemZ::CLRBCall:
4350b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLRB)
4360b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4370b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
4380b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
439e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4400b57cec5SDimitry Andric       .addImm(0);
4410b57cec5SDimitry Andric     break;
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric   case SystemZ::CLGRBCall:
4440b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
4450b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4460b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
4470b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
448e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4490b57cec5SDimitry Andric       .addImm(0);
4500b57cec5SDimitry Andric     break;
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric   case SystemZ::CLIBCall:
4530b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLIB)
4540b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4550b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
4560b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
457e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4580b57cec5SDimitry Andric       .addImm(0);
4590b57cec5SDimitry Andric     break;
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric   case SystemZ::CLGIBCall:
4620b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
4630b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4640b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
4650b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
466e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4670b57cec5SDimitry Andric       .addImm(0);
4680b57cec5SDimitry Andric     break;
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric   case SystemZ::TLS_GDCALL:
4710b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRASL)
4720b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
4730b57cec5SDimitry Andric       .addExpr(getTLSGetOffset(MF->getContext()))
4740b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD));
4750b57cec5SDimitry Andric     break;
4760b57cec5SDimitry Andric 
4770b57cec5SDimitry Andric   case SystemZ::TLS_LDCALL:
4780b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRASL)
4790b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
4800b57cec5SDimitry Andric       .addExpr(getTLSGetOffset(MF->getContext()))
4810b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM));
4820b57cec5SDimitry Andric     break;
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric   case SystemZ::GOT:
4850b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::LARL)
4860b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4870b57cec5SDimitry Andric       .addExpr(getGlobalOffsetTable(MF->getContext()));
4880b57cec5SDimitry Andric     break;
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric   case SystemZ::IILF64:
4910b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::IILF)
4920b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
4930b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm());
4940b57cec5SDimitry Andric     break;
4950b57cec5SDimitry Andric 
4960b57cec5SDimitry Andric   case SystemZ::IIHF64:
4970b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::IIHF)
4980b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
4990b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm());
5000b57cec5SDimitry Andric     break;
5010b57cec5SDimitry Andric 
5020b57cec5SDimitry Andric   case SystemZ::RISBHH:
5030b57cec5SDimitry Andric   case SystemZ::RISBHL:
5040b57cec5SDimitry Andric     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
5050b57cec5SDimitry Andric     break;
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric   case SystemZ::RISBLH:
5080b57cec5SDimitry Andric   case SystemZ::RISBLL:
5090b57cec5SDimitry Andric     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
5100b57cec5SDimitry Andric     break;
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric   case SystemZ::VLVGP32:
5130b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLVGP)
5140b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
5150b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg()))
5160b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()));
5170b57cec5SDimitry Andric     break;
5180b57cec5SDimitry Andric 
5190b57cec5SDimitry Andric   case SystemZ::VLR32:
5200b57cec5SDimitry Andric   case SystemZ::VLR64:
5210b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLR)
5220b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
5230b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()));
5240b57cec5SDimitry Andric     break;
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric   case SystemZ::VL:
5270b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
5280b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign);
5290b57cec5SDimitry Andric     break;
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric   case SystemZ::VST:
5320b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
5330b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign);
5340b57cec5SDimitry Andric     break;
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric   case SystemZ::VLM:
5370b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
5380b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign);
5390b57cec5SDimitry Andric     break;
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric   case SystemZ::VSTM:
5420b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
5430b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign);
5440b57cec5SDimitry Andric     break;
5450b57cec5SDimitry Andric 
5460b57cec5SDimitry Andric   case SystemZ::VL32:
5470b57cec5SDimitry Andric     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF);
5480b57cec5SDimitry Andric     break;
5490b57cec5SDimitry Andric 
5500b57cec5SDimitry Andric   case SystemZ::VL64:
5510b57cec5SDimitry Andric     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG);
5520b57cec5SDimitry Andric     break;
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric   case SystemZ::VST32:
5550b57cec5SDimitry Andric     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF);
5560b57cec5SDimitry Andric     break;
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric   case SystemZ::VST64:
5590b57cec5SDimitry Andric     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG);
5600b57cec5SDimitry Andric     break;
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric   case SystemZ::LFER:
5630b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLGVF)
5640b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg()))
5650b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()))
5660b57cec5SDimitry Andric       .addReg(0).addImm(0);
5670b57cec5SDimitry Andric     break;
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric   case SystemZ::LEFR:
5700b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLVGF)
5710b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
5720b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
5730b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
5740b57cec5SDimitry Andric       .addReg(0).addImm(0);
5750b57cec5SDimitry Andric     break;
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric #define LOWER_LOW(NAME)                                                 \
5780b57cec5SDimitry Andric   case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   LOWER_LOW(IILL);
5810b57cec5SDimitry Andric   LOWER_LOW(IILH);
5820b57cec5SDimitry Andric   LOWER_LOW(TMLL);
5830b57cec5SDimitry Andric   LOWER_LOW(TMLH);
5840b57cec5SDimitry Andric   LOWER_LOW(NILL);
5850b57cec5SDimitry Andric   LOWER_LOW(NILH);
5860b57cec5SDimitry Andric   LOWER_LOW(NILF);
5870b57cec5SDimitry Andric   LOWER_LOW(OILL);
5880b57cec5SDimitry Andric   LOWER_LOW(OILH);
5890b57cec5SDimitry Andric   LOWER_LOW(OILF);
5900b57cec5SDimitry Andric   LOWER_LOW(XILF);
5910b57cec5SDimitry Andric 
5920b57cec5SDimitry Andric #undef LOWER_LOW
5930b57cec5SDimitry Andric 
5940b57cec5SDimitry Andric #define LOWER_HIGH(NAME) \
5950b57cec5SDimitry Andric   case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
5960b57cec5SDimitry Andric 
5970b57cec5SDimitry Andric   LOWER_HIGH(IIHL);
5980b57cec5SDimitry Andric   LOWER_HIGH(IIHH);
5990b57cec5SDimitry Andric   LOWER_HIGH(TMHL);
6000b57cec5SDimitry Andric   LOWER_HIGH(TMHH);
6010b57cec5SDimitry Andric   LOWER_HIGH(NIHL);
6020b57cec5SDimitry Andric   LOWER_HIGH(NIHH);
6030b57cec5SDimitry Andric   LOWER_HIGH(NIHF);
6040b57cec5SDimitry Andric   LOWER_HIGH(OIHL);
6050b57cec5SDimitry Andric   LOWER_HIGH(OIHH);
6060b57cec5SDimitry Andric   LOWER_HIGH(OIHF);
6070b57cec5SDimitry Andric   LOWER_HIGH(XIHF);
6080b57cec5SDimitry Andric 
6090b57cec5SDimitry Andric #undef LOWER_HIGH
6100b57cec5SDimitry Andric 
6110b57cec5SDimitry Andric   case SystemZ::Serialize:
6120b57cec5SDimitry Andric     if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
6130b57cec5SDimitry Andric       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
6140b57cec5SDimitry Andric         .addImm(14).addReg(SystemZ::R0D);
6150b57cec5SDimitry Andric     else
6160b57cec5SDimitry Andric       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
6170b57cec5SDimitry Andric         .addImm(15).addReg(SystemZ::R0D);
6180b57cec5SDimitry Andric     break;
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric   // We want to emit "j .+2" for traps, jumping to the relative immediate field
6210b57cec5SDimitry Andric   // of the jump instruction, which is an illegal instruction. We cannot emit a
6220b57cec5SDimitry Andric   // "." symbol, so create and emit a temp label before the instruction and use
6230b57cec5SDimitry Andric   // that instead.
6240b57cec5SDimitry Andric   case SystemZ::Trap: {
6250b57cec5SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
6265ffd83dbSDimitry Andric     OutStreamer->emitLabel(DotSym);
6270b57cec5SDimitry Andric 
6280b57cec5SDimitry Andric     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
6290b57cec5SDimitry Andric     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
6300b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::J)
6310b57cec5SDimitry Andric       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
6320b57cec5SDimitry Andric     }
6330b57cec5SDimitry Andric     break;
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric   // Conditional traps will create a branch on condition instruction that jumps
6360b57cec5SDimitry Andric   // to the relative immediate field of the jump instruction. (eg. "jo .+2")
6370b57cec5SDimitry Andric   case SystemZ::CondTrap: {
6380b57cec5SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
6395ffd83dbSDimitry Andric     OutStreamer->emitLabel(DotSym);
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
6420b57cec5SDimitry Andric     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
6430b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRC)
6440b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
6450b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
6460b57cec5SDimitry Andric       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
6470b57cec5SDimitry Andric     }
6480b57cec5SDimitry Andric     break;
6490b57cec5SDimitry Andric 
6508bcb0991SDimitry Andric   case TargetOpcode::FENTRY_CALL:
6518bcb0991SDimitry Andric     LowerFENTRY_CALL(*MI, Lower);
6528bcb0991SDimitry Andric     return;
6538bcb0991SDimitry Andric 
6540b57cec5SDimitry Andric   case TargetOpcode::STACKMAP:
6550b57cec5SDimitry Andric     LowerSTACKMAP(*MI);
6560b57cec5SDimitry Andric     return;
6570b57cec5SDimitry Andric 
6580b57cec5SDimitry Andric   case TargetOpcode::PATCHPOINT:
6590b57cec5SDimitry Andric     LowerPATCHPOINT(*MI, Lower);
6600b57cec5SDimitry Andric     return;
6610b57cec5SDimitry Andric 
662fe6060f1SDimitry Andric   case SystemZ::EXRL_Pseudo: {
663fe6060f1SDimitry Andric     unsigned TargetInsOpc = MI->getOperand(0).getImm();
664fe6060f1SDimitry Andric     Register LenMinus1Reg = MI->getOperand(1).getReg();
665fe6060f1SDimitry Andric     Register DestReg = MI->getOperand(2).getReg();
666fe6060f1SDimitry Andric     int64_t DestDisp = MI->getOperand(3).getImm();
667fe6060f1SDimitry Andric     Register SrcReg = MI->getOperand(4).getReg();
668fe6060f1SDimitry Andric     int64_t SrcDisp = MI->getOperand(5).getImm();
669fe6060f1SDimitry Andric 
670349cc55cSDimitry Andric     SystemZTargetStreamer *TS = getTargetStreamer();
671fe6060f1SDimitry Andric     MCSymbol *DotSym = nullptr;
672fe6060f1SDimitry Andric     MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg)
673fe6060f1SDimitry Andric       .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp);
674349cc55cSDimitry Andric     SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
675349cc55cSDimitry Andric     SystemZTargetStreamer::EXRLT2SymMap::iterator I =
676349cc55cSDimitry Andric         TS->EXRLTargets2Sym.find(ET_STI);
677349cc55cSDimitry Andric     if (I != TS->EXRLTargets2Sym.end())
678fe6060f1SDimitry Andric       DotSym = I->second;
679fe6060f1SDimitry Andric     else
680349cc55cSDimitry Andric       TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
681fe6060f1SDimitry Andric     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
682fe6060f1SDimitry Andric     EmitToStreamer(
683fe6060f1SDimitry Andric         *OutStreamer,
684fe6060f1SDimitry Andric         MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));
685fe6060f1SDimitry Andric     return;
686fe6060f1SDimitry Andric   }
687fe6060f1SDimitry Andric 
6880b57cec5SDimitry Andric   default:
6890b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
6900b57cec5SDimitry Andric     break;
6910b57cec5SDimitry Andric   }
6920b57cec5SDimitry Andric   EmitToStreamer(*OutStreamer, LoweredMI);
6930b57cec5SDimitry Andric }
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric // Emit the largest nop instruction smaller than or equal to NumBytes
6960b57cec5SDimitry Andric // bytes.  Return the size of nop emitted.
6970b57cec5SDimitry Andric static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
6980b57cec5SDimitry Andric                         unsigned NumBytes, const MCSubtargetInfo &STI) {
6990b57cec5SDimitry Andric   if (NumBytes < 2) {
7000b57cec5SDimitry Andric     llvm_unreachable("Zero nops?");
7010b57cec5SDimitry Andric     return 0;
7020b57cec5SDimitry Andric   }
7030b57cec5SDimitry Andric   else if (NumBytes < 4) {
7045ffd83dbSDimitry Andric     OutStreamer.emitInstruction(
7055ffd83dbSDimitry Andric         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
7060b57cec5SDimitry Andric     return 2;
7070b57cec5SDimitry Andric   }
7080b57cec5SDimitry Andric   else if (NumBytes < 6) {
7095ffd83dbSDimitry Andric     OutStreamer.emitInstruction(
7105ffd83dbSDimitry Andric         MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
7110b57cec5SDimitry Andric         STI);
7120b57cec5SDimitry Andric     return 4;
7130b57cec5SDimitry Andric   }
7140b57cec5SDimitry Andric   else {
7150b57cec5SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
7160b57cec5SDimitry Andric     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
7175ffd83dbSDimitry Andric     OutStreamer.emitLabel(DotSym);
7185ffd83dbSDimitry Andric     OutStreamer.emitInstruction(
7195ffd83dbSDimitry Andric         MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
7200b57cec5SDimitry Andric     return 6;
7210b57cec5SDimitry Andric   }
7220b57cec5SDimitry Andric }
7230b57cec5SDimitry Andric 
7248bcb0991SDimitry Andric void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
7258bcb0991SDimitry Andric                                          SystemZMCInstLower &Lower) {
7268bcb0991SDimitry Andric   MCContext &Ctx = MF->getContext();
727480093f4SDimitry Andric   if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
728480093f4SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
72981ad6265SDimitry Andric     OutStreamer->pushSection();
73081ad6265SDimitry Andric     OutStreamer->switchSection(
731480093f4SDimitry Andric         Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
7325ffd83dbSDimitry Andric     OutStreamer->emitSymbolValue(DotSym, 8);
73381ad6265SDimitry Andric     OutStreamer->popSection();
7345ffd83dbSDimitry Andric     OutStreamer->emitLabel(DotSym);
735480093f4SDimitry Andric   }
736480093f4SDimitry Andric 
737480093f4SDimitry Andric   if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
7388bcb0991SDimitry Andric     EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
7398bcb0991SDimitry Andric     return;
7408bcb0991SDimitry Andric   }
7418bcb0991SDimitry Andric 
7428bcb0991SDimitry Andric   MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
7438bcb0991SDimitry Andric   const MCSymbolRefExpr *Op =
7448bcb0991SDimitry Andric       MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx);
7455ffd83dbSDimitry Andric   OutStreamer->emitInstruction(
7465ffd83dbSDimitry Andric       MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
7475ffd83dbSDimitry Andric       getSubtargetInfo());
7488bcb0991SDimitry Andric }
7498bcb0991SDimitry Andric 
7500b57cec5SDimitry Andric void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
75181ad6265SDimitry Andric   auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo();
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric   unsigned NumNOPBytes = MI.getOperand(1).getImm();
7540b57cec5SDimitry Andric 
755480093f4SDimitry Andric   auto &Ctx = OutStreamer->getContext();
756480093f4SDimitry Andric   MCSymbol *MILabel = Ctx.createTempSymbol();
7575ffd83dbSDimitry Andric   OutStreamer->emitLabel(MILabel);
758480093f4SDimitry Andric 
759480093f4SDimitry Andric   SM.recordStackMap(*MILabel, MI);
7600b57cec5SDimitry Andric   assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric   // Scan ahead to trim the shadow.
7630b57cec5SDimitry Andric   unsigned ShadowBytes = 0;
7640b57cec5SDimitry Andric   const MachineBasicBlock &MBB = *MI.getParent();
7650b57cec5SDimitry Andric   MachineBasicBlock::const_iterator MII(MI);
7660b57cec5SDimitry Andric   ++MII;
7670b57cec5SDimitry Andric   while (ShadowBytes < NumNOPBytes) {
7680b57cec5SDimitry Andric     if (MII == MBB.end() ||
7690b57cec5SDimitry Andric         MII->getOpcode() == TargetOpcode::PATCHPOINT ||
7700b57cec5SDimitry Andric         MII->getOpcode() == TargetOpcode::STACKMAP)
7710b57cec5SDimitry Andric       break;
7720b57cec5SDimitry Andric     ShadowBytes += TII->getInstSizeInBytes(*MII);
7730b57cec5SDimitry Andric     if (MII->isCall())
7740b57cec5SDimitry Andric       break;
7750b57cec5SDimitry Andric     ++MII;
7760b57cec5SDimitry Andric   }
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric   // Emit nops.
7790b57cec5SDimitry Andric   while (ShadowBytes < NumNOPBytes)
7800b57cec5SDimitry Andric     ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
7810b57cec5SDimitry Andric                            getSubtargetInfo());
7820b57cec5SDimitry Andric }
7830b57cec5SDimitry Andric 
7840b57cec5SDimitry Andric // Lower a patchpoint of the form:
7850b57cec5SDimitry Andric // [<def>], <id>, <numBytes>, <target>, <numArgs>
7860b57cec5SDimitry Andric void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
7870b57cec5SDimitry Andric                                         SystemZMCInstLower &Lower) {
788480093f4SDimitry Andric   auto &Ctx = OutStreamer->getContext();
789480093f4SDimitry Andric   MCSymbol *MILabel = Ctx.createTempSymbol();
7905ffd83dbSDimitry Andric   OutStreamer->emitLabel(MILabel);
791480093f4SDimitry Andric 
792480093f4SDimitry Andric   SM.recordPatchPoint(*MILabel, MI);
7930b57cec5SDimitry Andric   PatchPointOpers Opers(&MI);
7940b57cec5SDimitry Andric 
7950b57cec5SDimitry Andric   unsigned EncodedBytes = 0;
7960b57cec5SDimitry Andric   const MachineOperand &CalleeMO = Opers.getCallTarget();
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric   if (CalleeMO.isImm()) {
7990b57cec5SDimitry Andric     uint64_t CallTarget = CalleeMO.getImm();
8000b57cec5SDimitry Andric     if (CallTarget) {
8010b57cec5SDimitry Andric       unsigned ScratchIdx = -1;
8020b57cec5SDimitry Andric       unsigned ScratchReg = 0;
8030b57cec5SDimitry Andric       do {
8040b57cec5SDimitry Andric         ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
8050b57cec5SDimitry Andric         ScratchReg = MI.getOperand(ScratchIdx).getReg();
8060b57cec5SDimitry Andric       } while (ScratchReg == SystemZ::R0D);
8070b57cec5SDimitry Andric 
8080b57cec5SDimitry Andric       // Materialize the call target address
8090b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
8100b57cec5SDimitry Andric                                       .addReg(ScratchReg)
8110b57cec5SDimitry Andric                                       .addImm(CallTarget & 0xFFFFFFFF));
8120b57cec5SDimitry Andric       EncodedBytes += 6;
8130b57cec5SDimitry Andric       if (CallTarget >> 32) {
8140b57cec5SDimitry Andric         EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
8150b57cec5SDimitry Andric                                         .addReg(ScratchReg)
8160b57cec5SDimitry Andric                                         .addImm(CallTarget >> 32));
8170b57cec5SDimitry Andric         EncodedBytes += 6;
8180b57cec5SDimitry Andric       }
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
8210b57cec5SDimitry Andric                                      .addReg(SystemZ::R14D)
8220b57cec5SDimitry Andric                                      .addReg(ScratchReg));
8230b57cec5SDimitry Andric       EncodedBytes += 2;
8240b57cec5SDimitry Andric     }
8250b57cec5SDimitry Andric   } else if (CalleeMO.isGlobal()) {
8260b57cec5SDimitry Andric     const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT);
8270b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
8280b57cec5SDimitry Andric                                    .addReg(SystemZ::R14D)
8290b57cec5SDimitry Andric                                    .addExpr(Expr));
8300b57cec5SDimitry Andric     EncodedBytes += 6;
8310b57cec5SDimitry Andric   }
8320b57cec5SDimitry Andric 
8330b57cec5SDimitry Andric   // Emit padding.
8340b57cec5SDimitry Andric   unsigned NumBytes = Opers.getNumPatchBytes();
8350b57cec5SDimitry Andric   assert(NumBytes >= EncodedBytes &&
8360b57cec5SDimitry Andric          "Patchpoint can't request size less than the length of a call.");
8370b57cec5SDimitry Andric   assert((NumBytes - EncodedBytes) % 2 == 0 &&
8380b57cec5SDimitry Andric          "Invalid number of NOP bytes requested!");
8390b57cec5SDimitry Andric   while (EncodedBytes < NumBytes)
8400b57cec5SDimitry Andric     EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
8410b57cec5SDimitry Andric                             getSubtargetInfo());
8420b57cec5SDimitry Andric }
8430b57cec5SDimitry Andric 
844bdd1243dSDimitry Andric // The *alignment* of 128-bit vector types is different between the software
845bdd1243dSDimitry Andric // and hardware vector ABIs. If the there is an externally visible use of a
846bdd1243dSDimitry Andric // vector type in the module it should be annotated with an attribute.
847bdd1243dSDimitry Andric void SystemZAsmPrinter::emitAttributes(Module &M) {
848bdd1243dSDimitry Andric   if (M.getModuleFlag("s390x-visible-vector-ABI")) {
849bdd1243dSDimitry Andric     bool HasVectorFeature =
85006c3fb27SDimitry Andric       TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureVector);
851bdd1243dSDimitry Andric     OutStreamer->emitGNUAttribute(8, HasVectorFeature ? 2 : 1);
852bdd1243dSDimitry Andric   }
853bdd1243dSDimitry Andric }
854bdd1243dSDimitry Andric 
8550b57cec5SDimitry Andric // Convert a SystemZ-specific constant pool modifier into the associated
8560b57cec5SDimitry Andric // MCSymbolRefExpr variant kind.
8570b57cec5SDimitry Andric static MCSymbolRefExpr::VariantKind
8580b57cec5SDimitry Andric getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
8590b57cec5SDimitry Andric   switch (Modifier) {
8600b57cec5SDimitry Andric   case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
8610b57cec5SDimitry Andric   case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
8620b57cec5SDimitry Andric   case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
8630b57cec5SDimitry Andric   case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
8640b57cec5SDimitry Andric   }
8650b57cec5SDimitry Andric   llvm_unreachable("Invalid SystemCPModifier!");
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric 
8685ffd83dbSDimitry Andric void SystemZAsmPrinter::emitMachineConstantPoolValue(
8695ffd83dbSDimitry Andric     MachineConstantPoolValue *MCPV) {
8700b57cec5SDimitry Andric   auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
8710b57cec5SDimitry Andric 
8720b57cec5SDimitry Andric   const MCExpr *Expr =
8730b57cec5SDimitry Andric     MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
8740b57cec5SDimitry Andric                             getModifierVariantKind(ZCPV->getModifier()),
8750b57cec5SDimitry Andric                             OutContext);
8760b57cec5SDimitry Andric   uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
8770b57cec5SDimitry Andric 
8785ffd83dbSDimitry Andric   OutStreamer->emitValue(Expr, Size);
8790b57cec5SDimitry Andric }
8800b57cec5SDimitry Andric 
881bdd1243dSDimitry Andric static void printFormattedRegName(const MCAsmInfo *MAI, unsigned RegNo,
882bdd1243dSDimitry Andric                                   raw_ostream &OS) {
883bdd1243dSDimitry Andric   const char *RegName = SystemZInstPrinter::getRegisterName(RegNo);
884bdd1243dSDimitry Andric   if (MAI->getAssemblerDialect() == AD_HLASM) {
885bdd1243dSDimitry Andric     // Skip register prefix so that only register number is left
886bdd1243dSDimitry Andric     assert(isalpha(RegName[0]) && isdigit(RegName[1]));
887bdd1243dSDimitry Andric     OS << (RegName + 1);
888bdd1243dSDimitry Andric   } else
889bdd1243dSDimitry Andric     OS << '%' << RegName;
890bdd1243dSDimitry Andric }
891bdd1243dSDimitry Andric 
892bdd1243dSDimitry Andric static void printOperand(const MCOperand &MCOp, const MCAsmInfo *MAI,
893bdd1243dSDimitry Andric                          raw_ostream &OS) {
894bdd1243dSDimitry Andric   if (MCOp.isReg()) {
895bdd1243dSDimitry Andric     if (!MCOp.getReg())
896bdd1243dSDimitry Andric       OS << '0';
897bdd1243dSDimitry Andric     else
898bdd1243dSDimitry Andric       printFormattedRegName(MAI, MCOp.getReg(), OS);
899bdd1243dSDimitry Andric   } else if (MCOp.isImm())
900bdd1243dSDimitry Andric     OS << MCOp.getImm();
901bdd1243dSDimitry Andric   else if (MCOp.isExpr())
902bdd1243dSDimitry Andric     MCOp.getExpr()->print(OS, MAI);
903bdd1243dSDimitry Andric   else
904bdd1243dSDimitry Andric     llvm_unreachable("Invalid operand");
905bdd1243dSDimitry Andric }
906bdd1243dSDimitry Andric 
907bdd1243dSDimitry Andric static void printAddress(const MCAsmInfo *MAI, unsigned Base,
908bdd1243dSDimitry Andric                          const MCOperand &DispMO, unsigned Index,
909bdd1243dSDimitry Andric                          raw_ostream &OS) {
910bdd1243dSDimitry Andric   printOperand(DispMO, MAI, OS);
911bdd1243dSDimitry Andric   if (Base || Index) {
912bdd1243dSDimitry Andric     OS << '(';
913bdd1243dSDimitry Andric     if (Index) {
914bdd1243dSDimitry Andric       printFormattedRegName(MAI, Index, OS);
915bdd1243dSDimitry Andric       if (Base)
916bdd1243dSDimitry Andric         OS << ',';
917bdd1243dSDimitry Andric     }
918bdd1243dSDimitry Andric     if (Base)
919bdd1243dSDimitry Andric       printFormattedRegName(MAI, Base, OS);
920bdd1243dSDimitry Andric     OS << ')';
921bdd1243dSDimitry Andric   }
922bdd1243dSDimitry Andric }
923bdd1243dSDimitry Andric 
9240b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
9250b57cec5SDimitry Andric                                         const char *ExtraCode,
9260b57cec5SDimitry Andric                                         raw_ostream &OS) {
927fe6060f1SDimitry Andric   const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
928fe6060f1SDimitry Andric   const MachineOperand &MO = MI->getOperand(OpNo);
929fe6060f1SDimitry Andric   MCOperand MCOp;
930fe6060f1SDimitry Andric   if (ExtraCode) {
931fe6060f1SDimitry Andric     if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&
932fe6060f1SDimitry Andric         SystemZ::GR128BitRegClass.contains(MO.getReg()))
933fe6060f1SDimitry Andric       MCOp =
934fe6060f1SDimitry Andric           MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));
935fe6060f1SDimitry Andric     else
9360b57cec5SDimitry Andric       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
937fe6060f1SDimitry Andric   } else {
9380b57cec5SDimitry Andric     SystemZMCInstLower Lower(MF->getContext(), *this);
939fe6060f1SDimitry Andric     MCOp = Lower.lowerOperand(MO);
940fe6060f1SDimitry Andric   }
941bdd1243dSDimitry Andric   printOperand(MCOp, MAI, OS);
9420b57cec5SDimitry Andric   return false;
9430b57cec5SDimitry Andric }
9440b57cec5SDimitry Andric 
9450b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
9460b57cec5SDimitry Andric                                               unsigned OpNo,
9470b57cec5SDimitry Andric                                               const char *ExtraCode,
9480b57cec5SDimitry Andric                                               raw_ostream &OS) {
949349cc55cSDimitry Andric   printAddress(MAI, MI->getOperand(OpNo).getReg(),
950349cc55cSDimitry Andric                MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()),
9510b57cec5SDimitry Andric                MI->getOperand(OpNo + 2).getReg(), OS);
9520b57cec5SDimitry Andric   return false;
9530b57cec5SDimitry Andric }
9540b57cec5SDimitry Andric 
9555ffd83dbSDimitry Andric void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
95606c3fb27SDimitry Andric   auto TT = OutContext.getTargetTriple();
95706c3fb27SDimitry Andric   if (TT.isOSzOS()) {
95806c3fb27SDimitry Andric     emitADASection();
959*5f757f3fSDimitry Andric     emitIDRLSection(M);
96006c3fb27SDimitry Andric   }
961bdd1243dSDimitry Andric   emitAttributes(M);
9620b57cec5SDimitry Andric }
9630b57cec5SDimitry Andric 
96406c3fb27SDimitry Andric void SystemZAsmPrinter::emitADASection() {
96506c3fb27SDimitry Andric   OutStreamer->pushSection();
96606c3fb27SDimitry Andric 
96706c3fb27SDimitry Andric   const unsigned PointerSize = getDataLayout().getPointerSize();
96806c3fb27SDimitry Andric   OutStreamer->switchSection(getObjFileLowering().getADASection());
96906c3fb27SDimitry Andric 
97006c3fb27SDimitry Andric   unsigned EmittedBytes = 0;
97106c3fb27SDimitry Andric   for (auto &Entry : ADATable.getTable()) {
97206c3fb27SDimitry Andric     const MCSymbol *Sym;
97306c3fb27SDimitry Andric     unsigned SlotKind;
97406c3fb27SDimitry Andric     std::tie(Sym, SlotKind) = Entry.first;
97506c3fb27SDimitry Andric     unsigned Offset = Entry.second;
97606c3fb27SDimitry Andric     assert(Offset == EmittedBytes && "Offset not as expected");
97706c3fb27SDimitry Andric     (void)EmittedBytes;
97806c3fb27SDimitry Andric #define EMIT_COMMENT(Str)                                                      \
97906c3fb27SDimitry Andric   OutStreamer->AddComment(Twine("Offset ")                                     \
98006c3fb27SDimitry Andric                               .concat(utostr(Offset))                          \
98106c3fb27SDimitry Andric                               .concat(" " Str " ")                             \
98206c3fb27SDimitry Andric                               .concat(Sym->getName()));
98306c3fb27SDimitry Andric     switch (SlotKind) {
98406c3fb27SDimitry Andric     case SystemZII::MO_ADA_DIRECT_FUNC_DESC:
98506c3fb27SDimitry Andric       // Language Environment DLL logic requires function descriptors, for
98606c3fb27SDimitry Andric       // imported functions, that are placed in the ADA to be 8 byte aligned.
98706c3fb27SDimitry Andric       EMIT_COMMENT("function descriptor of");
98806c3fb27SDimitry Andric       OutStreamer->emitValue(
98906c3fb27SDimitry Andric           SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_RCon,
99006c3fb27SDimitry Andric                                 MCSymbolRefExpr::create(Sym, OutContext),
99106c3fb27SDimitry Andric                                 OutContext),
99206c3fb27SDimitry Andric           PointerSize);
99306c3fb27SDimitry Andric       OutStreamer->emitValue(
99406c3fb27SDimitry Andric           SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_VCon,
99506c3fb27SDimitry Andric                                 MCSymbolRefExpr::create(Sym, OutContext),
99606c3fb27SDimitry Andric                                 OutContext),
99706c3fb27SDimitry Andric           PointerSize);
99806c3fb27SDimitry Andric       EmittedBytes += PointerSize * 2;
99906c3fb27SDimitry Andric       break;
100006c3fb27SDimitry Andric     case SystemZII::MO_ADA_DATA_SYMBOL_ADDR:
100106c3fb27SDimitry Andric       EMIT_COMMENT("pointer to data symbol");
100206c3fb27SDimitry Andric       OutStreamer->emitValue(
100306c3fb27SDimitry Andric           SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_None,
100406c3fb27SDimitry Andric                                 MCSymbolRefExpr::create(Sym, OutContext),
100506c3fb27SDimitry Andric                                 OutContext),
100606c3fb27SDimitry Andric           PointerSize);
100706c3fb27SDimitry Andric       EmittedBytes += PointerSize;
100806c3fb27SDimitry Andric       break;
100906c3fb27SDimitry Andric     case SystemZII::MO_ADA_INDIRECT_FUNC_DESC: {
101006c3fb27SDimitry Andric       MCSymbol *Alias = OutContext.createTempSymbol(
101106c3fb27SDimitry Andric           Twine(Sym->getName()).concat("@indirect"));
101206c3fb27SDimitry Andric       OutStreamer->emitAssignment(Alias,
101306c3fb27SDimitry Andric                                   MCSymbolRefExpr::create(Sym, OutContext));
101406c3fb27SDimitry Andric       OutStreamer->emitSymbolAttribute(Alias, MCSA_IndirectSymbol);
101506c3fb27SDimitry Andric 
101606c3fb27SDimitry Andric       EMIT_COMMENT("pointer to function descriptor");
101706c3fb27SDimitry Andric       OutStreamer->emitValue(
101806c3fb27SDimitry Andric           SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_VCon,
101906c3fb27SDimitry Andric                                 MCSymbolRefExpr::create(Alias, OutContext),
102006c3fb27SDimitry Andric                                 OutContext),
102106c3fb27SDimitry Andric           PointerSize);
102206c3fb27SDimitry Andric       EmittedBytes += PointerSize;
102306c3fb27SDimitry Andric       break;
102406c3fb27SDimitry Andric     }
102506c3fb27SDimitry Andric     default:
102606c3fb27SDimitry Andric       llvm_unreachable("Unexpected slot kind");
102706c3fb27SDimitry Andric     }
102806c3fb27SDimitry Andric #undef EMIT_COMMENT
102906c3fb27SDimitry Andric   }
103006c3fb27SDimitry Andric   OutStreamer->popSection();
103106c3fb27SDimitry Andric }
103206c3fb27SDimitry Andric 
1033*5f757f3fSDimitry Andric static std::string getProductID(Module &M) {
1034*5f757f3fSDimitry Andric   std::string ProductID;
1035*5f757f3fSDimitry Andric   if (auto *MD = M.getModuleFlag("zos_product_id"))
1036*5f757f3fSDimitry Andric     ProductID = cast<MDString>(MD)->getString().str();
1037*5f757f3fSDimitry Andric   if (ProductID.empty())
1038*5f757f3fSDimitry Andric     ProductID = "LLVM";
1039*5f757f3fSDimitry Andric   return ProductID;
1040*5f757f3fSDimitry Andric }
1041*5f757f3fSDimitry Andric 
1042*5f757f3fSDimitry Andric static uint32_t getProductVersion(Module &M) {
1043*5f757f3fSDimitry Andric   if (auto *VersionVal = mdconst::extract_or_null<ConstantInt>(
1044*5f757f3fSDimitry Andric           M.getModuleFlag("zos_product_major_version")))
1045*5f757f3fSDimitry Andric     return VersionVal->getZExtValue();
1046*5f757f3fSDimitry Andric   return LLVM_VERSION_MAJOR;
1047*5f757f3fSDimitry Andric }
1048*5f757f3fSDimitry Andric 
1049*5f757f3fSDimitry Andric static uint32_t getProductRelease(Module &M) {
1050*5f757f3fSDimitry Andric   if (auto *ReleaseVal = mdconst::extract_or_null<ConstantInt>(
1051*5f757f3fSDimitry Andric           M.getModuleFlag("zos_product_minor_version")))
1052*5f757f3fSDimitry Andric     return ReleaseVal->getZExtValue();
1053*5f757f3fSDimitry Andric   return LLVM_VERSION_MINOR;
1054*5f757f3fSDimitry Andric }
1055*5f757f3fSDimitry Andric 
1056*5f757f3fSDimitry Andric static uint32_t getProductPatch(Module &M) {
1057*5f757f3fSDimitry Andric   if (auto *PatchVal = mdconst::extract_or_null<ConstantInt>(
1058*5f757f3fSDimitry Andric           M.getModuleFlag("zos_product_patchlevel")))
1059*5f757f3fSDimitry Andric     return PatchVal->getZExtValue();
1060*5f757f3fSDimitry Andric   return LLVM_VERSION_PATCH;
1061*5f757f3fSDimitry Andric }
1062*5f757f3fSDimitry Andric 
1063*5f757f3fSDimitry Andric static time_t getTranslationTime(Module &M) {
1064*5f757f3fSDimitry Andric   std::time_t Time = 0;
1065*5f757f3fSDimitry Andric   if (auto *Val = mdconst::extract_or_null<ConstantInt>(
1066*5f757f3fSDimitry Andric           M.getModuleFlag("zos_translation_time"))) {
1067*5f757f3fSDimitry Andric     long SecondsSinceEpoch = Val->getSExtValue();
1068*5f757f3fSDimitry Andric     Time = static_cast<time_t>(SecondsSinceEpoch);
1069*5f757f3fSDimitry Andric   }
1070*5f757f3fSDimitry Andric   return Time;
1071*5f757f3fSDimitry Andric }
1072*5f757f3fSDimitry Andric 
1073*5f757f3fSDimitry Andric void SystemZAsmPrinter::emitIDRLSection(Module &M) {
1074*5f757f3fSDimitry Andric   OutStreamer->pushSection();
1075*5f757f3fSDimitry Andric   OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
1076*5f757f3fSDimitry Andric   constexpr unsigned IDRLDataLength = 30;
1077*5f757f3fSDimitry Andric   std::time_t Time = getTranslationTime(M);
1078*5f757f3fSDimitry Andric 
1079*5f757f3fSDimitry Andric   uint32_t ProductVersion = getProductVersion(M);
1080*5f757f3fSDimitry Andric   uint32_t ProductRelease = getProductRelease(M);
1081*5f757f3fSDimitry Andric 
1082*5f757f3fSDimitry Andric   std::string ProductID = getProductID(M);
1083*5f757f3fSDimitry Andric 
1084*5f757f3fSDimitry Andric   SmallString<IDRLDataLength + 1> TempStr;
1085*5f757f3fSDimitry Andric   raw_svector_ostream O(TempStr);
1086*5f757f3fSDimitry Andric   O << formatv("{0,-10}{1,0-2:d}{2,0-2:d}{3:%Y%m%d%H%M%S}{4,0-2}",
1087*5f757f3fSDimitry Andric                ProductID.substr(0, 10).c_str(), ProductVersion, ProductRelease,
1088*5f757f3fSDimitry Andric                llvm::sys::toUtcTime(Time), "0");
1089*5f757f3fSDimitry Andric   SmallString<IDRLDataLength> Data;
1090*5f757f3fSDimitry Andric   ConverterEBCDIC::convertToEBCDIC(TempStr, Data);
1091*5f757f3fSDimitry Andric 
1092*5f757f3fSDimitry Andric   OutStreamer->emitInt8(0);               // Reserved.
1093*5f757f3fSDimitry Andric   OutStreamer->emitInt8(3);               // Format.
1094*5f757f3fSDimitry Andric   OutStreamer->emitInt16(IDRLDataLength); // Length.
1095*5f757f3fSDimitry Andric   OutStreamer->emitBytes(Data.str());
1096*5f757f3fSDimitry Andric   OutStreamer->popSection();
1097*5f757f3fSDimitry Andric }
1098*5f757f3fSDimitry Andric 
109981ad6265SDimitry Andric void SystemZAsmPrinter::emitFunctionBodyEnd() {
110081ad6265SDimitry Andric   if (TM.getTargetTriple().isOSzOS()) {
110181ad6265SDimitry Andric     // Emit symbol for the end of function if the z/OS target streamer
110281ad6265SDimitry Andric     // is used. This is needed to calculate the size of the function.
110381ad6265SDimitry Andric     MCSymbol *FnEndSym = createTempSymbol("func_end");
110481ad6265SDimitry Andric     OutStreamer->emitLabel(FnEndSym);
110581ad6265SDimitry Andric 
110681ad6265SDimitry Andric     OutStreamer->pushSection();
110781ad6265SDimitry Andric     OutStreamer->switchSection(getObjFileLowering().getPPA1Section());
110881ad6265SDimitry Andric     emitPPA1(FnEndSym);
110981ad6265SDimitry Andric     OutStreamer->popSection();
111081ad6265SDimitry Andric 
111181ad6265SDimitry Andric     CurrentFnPPA1Sym = nullptr;
111281ad6265SDimitry Andric     CurrentFnEPMarkerSym = nullptr;
111381ad6265SDimitry Andric   }
111481ad6265SDimitry Andric }
111581ad6265SDimitry Andric 
111681ad6265SDimitry Andric static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
1117*5f757f3fSDimitry Andric                           bool StackProtector, bool FPRMask, bool VRMask,
1118*5f757f3fSDimitry Andric                           bool HasName) {
111981ad6265SDimitry Andric   enum class PPA1Flag1 : uint8_t {
112081ad6265SDimitry Andric     DSA64Bit = (0x80 >> 0),
112181ad6265SDimitry Andric     VarArg = (0x80 >> 7),
112281ad6265SDimitry Andric     LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit)
112381ad6265SDimitry Andric   };
112481ad6265SDimitry Andric   enum class PPA1Flag2 : uint8_t {
112581ad6265SDimitry Andric     ExternalProcedure = (0x80 >> 0),
112681ad6265SDimitry Andric     STACKPROTECTOR = (0x80 >> 3),
112781ad6265SDimitry Andric     LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure)
112881ad6265SDimitry Andric   };
112981ad6265SDimitry Andric   enum class PPA1Flag3 : uint8_t {
113081ad6265SDimitry Andric     FPRMask = (0x80 >> 2),
113181ad6265SDimitry Andric     LLVM_MARK_AS_BITMASK_ENUM(FPRMask)
113281ad6265SDimitry Andric   };
113381ad6265SDimitry Andric   enum class PPA1Flag4 : uint8_t {
113481ad6265SDimitry Andric     EPMOffsetPresent = (0x80 >> 0),
113581ad6265SDimitry Andric     VRMask = (0x80 >> 2),
113681ad6265SDimitry Andric     ProcedureNamePresent = (0x80 >> 7),
113781ad6265SDimitry Andric     LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent)
113881ad6265SDimitry Andric   };
113981ad6265SDimitry Andric 
114081ad6265SDimitry Andric   // Declare optional section flags that can be modified.
114181ad6265SDimitry Andric   auto Flags1 = PPA1Flag1(0);
114281ad6265SDimitry Andric   auto Flags2 = PPA1Flag2::ExternalProcedure;
114381ad6265SDimitry Andric   auto Flags3 = PPA1Flag3(0);
1144*5f757f3fSDimitry Andric   auto Flags4 = PPA1Flag4::EPMOffsetPresent;
114581ad6265SDimitry Andric 
114681ad6265SDimitry Andric   Flags1 |= PPA1Flag1::DSA64Bit;
114781ad6265SDimitry Andric 
114881ad6265SDimitry Andric   if (VarArg)
114981ad6265SDimitry Andric     Flags1 |= PPA1Flag1::VarArg;
115081ad6265SDimitry Andric 
115181ad6265SDimitry Andric   if (StackProtector)
115281ad6265SDimitry Andric     Flags2 |= PPA1Flag2::STACKPROTECTOR;
115381ad6265SDimitry Andric 
115481ad6265SDimitry Andric   // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in.
115581ad6265SDimitry Andric   if (FPRMask)
115681ad6265SDimitry Andric     Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag.
115781ad6265SDimitry Andric 
115881ad6265SDimitry Andric   if (VRMask)
115981ad6265SDimitry Andric     Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag.
116081ad6265SDimitry Andric 
1161*5f757f3fSDimitry Andric   if (HasName)
1162*5f757f3fSDimitry Andric     Flags4 |= PPA1Flag4::ProcedureNamePresent; // Add optional name block.
1163*5f757f3fSDimitry Andric 
116481ad6265SDimitry Andric   OutStreamer->AddComment("PPA1 Flags 1");
116581ad6265SDimitry Andric   if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit)
116681ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 0: 1 = 64-bit DSA");
116781ad6265SDimitry Andric   else
116881ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 0: 0 = 32-bit DSA");
116981ad6265SDimitry Andric   if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg)
117081ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 7: 1 = Vararg function");
117181ad6265SDimitry Andric   OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1.
117281ad6265SDimitry Andric 
117381ad6265SDimitry Andric   OutStreamer->AddComment("PPA1 Flags 2");
117481ad6265SDimitry Andric   if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure)
117581ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 0: 1 = External procedure");
117681ad6265SDimitry Andric   if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR)
117781ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 3: 1 = STACKPROTECT is enabled");
117881ad6265SDimitry Andric   else
117981ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 3: 0 = STACKPROTECT is not enabled");
118081ad6265SDimitry Andric   OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2.
118181ad6265SDimitry Andric 
118281ad6265SDimitry Andric   OutStreamer->AddComment("PPA1 Flags 3");
118381ad6265SDimitry Andric   if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask)
118481ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 2: 1 = FP Reg Mask is in optional area");
118581ad6265SDimitry Andric   OutStreamer->emitInt8(
118681ad6265SDimitry Andric       static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections).
118781ad6265SDimitry Andric 
118881ad6265SDimitry Andric   OutStreamer->AddComment("PPA1 Flags 4");
118981ad6265SDimitry Andric   if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask)
119081ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 2: 1 = Vector Reg Mask is in optional area");
1191*5f757f3fSDimitry Andric   if ((Flags4 & PPA1Flag4::ProcedureNamePresent) ==
1192*5f757f3fSDimitry Andric       PPA1Flag4::ProcedureNamePresent)
1193*5f757f3fSDimitry Andric     OutStreamer->AddComment("  Bit 7: 1 = Name Length and Name");
119481ad6265SDimitry Andric   OutStreamer->emitInt8(static_cast<uint8_t>(
119581ad6265SDimitry Andric       Flags4)); // Flags 4 (optional sections, always emit these).
119681ad6265SDimitry Andric }
119781ad6265SDimitry Andric 
1198*5f757f3fSDimitry Andric static void emitPPA1Name(std::unique_ptr<MCStreamer> &OutStreamer,
1199*5f757f3fSDimitry Andric                          StringRef OutName) {
1200*5f757f3fSDimitry Andric   size_t NameSize = OutName.size();
1201*5f757f3fSDimitry Andric   uint16_t OutSize;
1202*5f757f3fSDimitry Andric   if (NameSize < UINT16_MAX) {
1203*5f757f3fSDimitry Andric     OutSize = static_cast<uint16_t>(NameSize);
1204*5f757f3fSDimitry Andric   } else {
1205*5f757f3fSDimitry Andric     OutName = OutName.substr(0, UINT16_MAX);
1206*5f757f3fSDimitry Andric     OutSize = UINT16_MAX;
1207*5f757f3fSDimitry Andric   }
1208*5f757f3fSDimitry Andric   // Emit padding to ensure that the next optional field word-aligned.
1209*5f757f3fSDimitry Andric   uint8_t ExtraZeros = 4 - ((2 + OutSize) % 4);
1210*5f757f3fSDimitry Andric 
1211*5f757f3fSDimitry Andric   SmallString<512> OutnameConv;
1212*5f757f3fSDimitry Andric   ConverterEBCDIC::convertToEBCDIC(OutName, OutnameConv);
1213*5f757f3fSDimitry Andric   OutName = OutnameConv.str();
1214*5f757f3fSDimitry Andric 
1215*5f757f3fSDimitry Andric   OutStreamer->AddComment("Length of Name");
1216*5f757f3fSDimitry Andric   OutStreamer->emitInt16(OutSize);
1217*5f757f3fSDimitry Andric   OutStreamer->AddComment("Name of Function");
1218*5f757f3fSDimitry Andric   OutStreamer->emitBytes(OutName);
1219*5f757f3fSDimitry Andric   OutStreamer->emitZeros(ExtraZeros);
1220*5f757f3fSDimitry Andric }
1221*5f757f3fSDimitry Andric 
122281ad6265SDimitry Andric void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
1223*5f757f3fSDimitry Andric   assert(PPA2Sym != nullptr && "PPA2 Symbol not defined");
1224*5f757f3fSDimitry Andric 
122581ad6265SDimitry Andric   const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
122681ad6265SDimitry Andric   const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
122781ad6265SDimitry Andric   const auto TargetHasVector = Subtarget.hasVector();
122881ad6265SDimitry Andric 
122981ad6265SDimitry Andric   const SystemZMachineFunctionInfo *ZFI =
123081ad6265SDimitry Andric       MF->getInfo<SystemZMachineFunctionInfo>();
123181ad6265SDimitry Andric   const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>(
123281ad6265SDimitry Andric       Subtarget.getFrameLowering());
123381ad6265SDimitry Andric   const MachineFrameInfo &MFFrame = MF->getFrameInfo();
123481ad6265SDimitry Andric 
123581ad6265SDimitry Andric   // Get saved GPR/FPR/VPR masks.
123681ad6265SDimitry Andric   const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
123781ad6265SDimitry Andric   uint16_t SavedGPRMask = 0;
123881ad6265SDimitry Andric   uint16_t SavedFPRMask = 0;
123981ad6265SDimitry Andric   uint8_t SavedVRMask = 0;
124081ad6265SDimitry Andric   int64_t OffsetFPR = 0;
124181ad6265SDimitry Andric   int64_t OffsetVR = 0;
124281ad6265SDimitry Andric   const int64_t TopOfStack =
124381ad6265SDimitry Andric       MFFrame.getOffsetAdjustment() + MFFrame.getStackSize();
124481ad6265SDimitry Andric 
124581ad6265SDimitry Andric   // Loop over the spilled registers. The CalleeSavedInfo can't be used because
124681ad6265SDimitry Andric   // it does not contain all spilled registers.
124781ad6265SDimitry Andric   for (unsigned I = ZFI->getSpillGPRRegs().LowGPR,
124881ad6265SDimitry Andric                 E = ZFI->getSpillGPRRegs().HighGPR;
124981ad6265SDimitry Andric        I && E && I <= E; ++I) {
125081ad6265SDimitry Andric     unsigned V = TRI->getEncodingValue((Register)I);
125181ad6265SDimitry Andric     assert(V < 16 && "GPR index out of range");
125281ad6265SDimitry Andric     SavedGPRMask |= 1 << (15 - V);
125381ad6265SDimitry Andric   }
125481ad6265SDimitry Andric 
125581ad6265SDimitry Andric   for (auto &CS : CSI) {
125681ad6265SDimitry Andric     unsigned Reg = CS.getReg();
125781ad6265SDimitry Andric     unsigned I = TRI->getEncodingValue(Reg);
125881ad6265SDimitry Andric 
125981ad6265SDimitry Andric     if (SystemZ::FP64BitRegClass.contains(Reg)) {
126081ad6265SDimitry Andric       assert(I < 16 && "FPR index out of range");
126181ad6265SDimitry Andric       SavedFPRMask |= 1 << (15 - I);
126281ad6265SDimitry Andric       int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
126381ad6265SDimitry Andric       if (Temp < OffsetFPR)
126481ad6265SDimitry Andric         OffsetFPR = Temp;
126581ad6265SDimitry Andric     } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
126681ad6265SDimitry Andric       assert(I >= 16 && I <= 23 && "VPR index out of range");
126781ad6265SDimitry Andric       unsigned BitNum = I - 16;
126881ad6265SDimitry Andric       SavedVRMask |= 1 << (7 - BitNum);
126981ad6265SDimitry Andric       int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
127081ad6265SDimitry Andric       if (Temp < OffsetVR)
127181ad6265SDimitry Andric         OffsetVR = Temp;
127281ad6265SDimitry Andric     }
127381ad6265SDimitry Andric   }
127481ad6265SDimitry Andric 
127581ad6265SDimitry Andric   // Adjust the offset.
127681ad6265SDimitry Andric   OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0;
127781ad6265SDimitry Andric   OffsetVR += (OffsetVR < 0) ? TopOfStack : 0;
127881ad6265SDimitry Andric 
127981ad6265SDimitry Andric   // Get alloca register.
128081ad6265SDimitry Andric   uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF));
128181ad6265SDimitry Andric   uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0;
128281ad6265SDimitry Andric   assert(AllocaReg < 16 && "Can't have alloca register larger than 15");
128381ad6265SDimitry Andric   (void)AllocaReg;
128481ad6265SDimitry Andric 
128581ad6265SDimitry Andric   // Build FPR save area offset.
128681ad6265SDimitry Andric   uint32_t FrameAndFPROffset = 0;
128781ad6265SDimitry Andric   if (SavedFPRMask) {
128881ad6265SDimitry Andric     uint64_t FPRSaveAreaOffset = OffsetFPR;
128981ad6265SDimitry Andric     assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range");
129081ad6265SDimitry Andric 
129181ad6265SDimitry Andric     FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
129281ad6265SDimitry Andric     FrameAndFPROffset |= FrameReg << 28;                // Put into top 4 bits.
129381ad6265SDimitry Andric   }
129481ad6265SDimitry Andric 
129581ad6265SDimitry Andric   // Build VR save area offset.
129681ad6265SDimitry Andric   uint32_t FrameAndVROffset = 0;
129781ad6265SDimitry Andric   if (TargetHasVector && SavedVRMask) {
129881ad6265SDimitry Andric     uint64_t VRSaveAreaOffset = OffsetVR;
129981ad6265SDimitry Andric     assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range");
130081ad6265SDimitry Andric 
130181ad6265SDimitry Andric     FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
130281ad6265SDimitry Andric     FrameAndVROffset |= FrameReg << 28;               // Put into top 4 bits.
130381ad6265SDimitry Andric   }
130481ad6265SDimitry Andric 
130581ad6265SDimitry Andric   // Emit PPA1 section.
130681ad6265SDimitry Andric   OutStreamer->AddComment("PPA1");
130781ad6265SDimitry Andric   OutStreamer->emitLabel(CurrentFnPPA1Sym);
130881ad6265SDimitry Andric   OutStreamer->AddComment("Version");
130981ad6265SDimitry Andric   OutStreamer->emitInt8(0x02); // Version.
131081ad6265SDimitry Andric   OutStreamer->AddComment("LE Signature X'CE'");
131181ad6265SDimitry Andric   OutStreamer->emitInt8(0xCE); // CEL signature.
131281ad6265SDimitry Andric   OutStreamer->AddComment("Saved GPR Mask");
131381ad6265SDimitry Andric   OutStreamer->emitInt16(SavedGPRMask);
1314*5f757f3fSDimitry Andric   OutStreamer->AddComment("Offset to PPA2");
1315*5f757f3fSDimitry Andric   OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CurrentFnPPA1Sym, 4);
1316*5f757f3fSDimitry Andric 
1317*5f757f3fSDimitry Andric   bool HasName =
1318*5f757f3fSDimitry Andric       MF->getFunction().hasName() && MF->getFunction().getName().size() > 0;
131981ad6265SDimitry Andric 
132081ad6265SDimitry Andric   emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(),
132181ad6265SDimitry Andric                 MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,
1322*5f757f3fSDimitry Andric                 TargetHasVector && SavedVRMask != 0, HasName);
132381ad6265SDimitry Andric 
132481ad6265SDimitry Andric   OutStreamer->AddComment("Length/4 of Parms");
132581ad6265SDimitry Andric   OutStreamer->emitInt16(
132606c3fb27SDimitry Andric       static_cast<uint16_t>(ZFI->getSizeOfFnParams() / 4)); // Parms/4.
132781ad6265SDimitry Andric   OutStreamer->AddComment("Length of Code");
132881ad6265SDimitry Andric   OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4);
132981ad6265SDimitry Andric 
133081ad6265SDimitry Andric   // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).
133181ad6265SDimitry Andric   if (SavedFPRMask) {
133281ad6265SDimitry Andric     OutStreamer->AddComment("FPR mask");
133381ad6265SDimitry Andric     OutStreamer->emitInt16(SavedFPRMask);
133481ad6265SDimitry Andric     OutStreamer->AddComment("AR mask");
133581ad6265SDimitry Andric     OutStreamer->emitInt16(0); // AR Mask, unused currently.
133681ad6265SDimitry Andric     OutStreamer->AddComment("FPR Save Area Locator");
133781ad6265SDimitry Andric     OutStreamer->AddComment(Twine("  Bit 0-3: Register R")
133881ad6265SDimitry Andric                                 .concat(utostr(FrameAndFPROffset >> 28))
133981ad6265SDimitry Andric                                 .str());
134081ad6265SDimitry Andric     OutStreamer->AddComment(Twine("  Bit 4-31: Offset ")
134181ad6265SDimitry Andric                                 .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF))
134281ad6265SDimitry Andric                                 .str());
134381ad6265SDimitry Andric     OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with
134481ad6265SDimitry Andric                                                // register to add value to
134581ad6265SDimitry Andric                                                // (alloca reg).
134681ad6265SDimitry Andric   }
134781ad6265SDimitry Andric 
134881ad6265SDimitry Andric   // Emit saved VR mask to VR save area.
134981ad6265SDimitry Andric   if (TargetHasVector && SavedVRMask) {
135081ad6265SDimitry Andric     OutStreamer->AddComment("VR mask");
135181ad6265SDimitry Andric     OutStreamer->emitInt8(SavedVRMask);
135281ad6265SDimitry Andric     OutStreamer->emitInt8(0);  // Reserved.
135381ad6265SDimitry Andric     OutStreamer->emitInt16(0); // Also reserved.
135481ad6265SDimitry Andric     OutStreamer->AddComment("VR Save Area Locator");
135581ad6265SDimitry Andric     OutStreamer->AddComment(Twine("  Bit 0-3: Register R")
135681ad6265SDimitry Andric                                 .concat(utostr(FrameAndVROffset >> 28))
135781ad6265SDimitry Andric                                 .str());
135881ad6265SDimitry Andric     OutStreamer->AddComment(Twine("  Bit 4-31: Offset ")
135981ad6265SDimitry Andric                                 .concat(utostr(FrameAndVROffset & 0x0FFFFFFF))
136081ad6265SDimitry Andric                                 .str());
136181ad6265SDimitry Andric     OutStreamer->emitInt32(FrameAndVROffset);
136281ad6265SDimitry Andric   }
136381ad6265SDimitry Andric 
1364*5f757f3fSDimitry Andric   // Emit name length and name optional section (0x01 of flags 4)
1365*5f757f3fSDimitry Andric   if (HasName)
1366*5f757f3fSDimitry Andric     emitPPA1Name(OutStreamer, MF->getFunction().getName());
1367*5f757f3fSDimitry Andric 
136881ad6265SDimitry Andric   // Emit offset to entry point optional section (0x80 of flags 4).
136981ad6265SDimitry Andric   OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym,
137081ad6265SDimitry Andric                                       4);
137181ad6265SDimitry Andric }
137281ad6265SDimitry Andric 
1373*5f757f3fSDimitry Andric void SystemZAsmPrinter::emitStartOfAsmFile(Module &M) {
1374*5f757f3fSDimitry Andric   if (TM.getTargetTriple().isOSzOS())
1375*5f757f3fSDimitry Andric     emitPPA2(M);
1376*5f757f3fSDimitry Andric   AsmPrinter::emitStartOfAsmFile(M);
1377*5f757f3fSDimitry Andric }
1378*5f757f3fSDimitry Andric 
1379*5f757f3fSDimitry Andric void SystemZAsmPrinter::emitPPA2(Module &M) {
1380*5f757f3fSDimitry Andric   OutStreamer->pushSection();
1381*5f757f3fSDimitry Andric   OutStreamer->switchSection(getObjFileLowering().getPPA2Section());
1382*5f757f3fSDimitry Andric   MCContext &OutContext = OutStreamer->getContext();
1383*5f757f3fSDimitry Andric   // Make CELQSTRT symbol.
1384*5f757f3fSDimitry Andric   const char *StartSymbolName = "CELQSTRT";
1385*5f757f3fSDimitry Andric   MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);
1386*5f757f3fSDimitry Andric 
1387*5f757f3fSDimitry Andric   // Create symbol and assign to class field for use in PPA1.
1388*5f757f3fSDimitry Andric   PPA2Sym = OutContext.createTempSymbol("PPA2", false);
1389*5f757f3fSDimitry Andric   MCSymbol *DateVersionSym = OutContext.createTempSymbol("DVS", false);
1390*5f757f3fSDimitry Andric 
1391*5f757f3fSDimitry Andric   std::time_t Time = getTranslationTime(M);
1392*5f757f3fSDimitry Andric   SmallString<15> CompilationTime; // 14 + null
1393*5f757f3fSDimitry Andric   raw_svector_ostream O(CompilationTime);
1394*5f757f3fSDimitry Andric   O << formatv("{0:%Y%m%d%H%M%S}", llvm::sys::toUtcTime(Time));
1395*5f757f3fSDimitry Andric 
1396*5f757f3fSDimitry Andric   uint32_t ProductVersion = getProductVersion(M),
1397*5f757f3fSDimitry Andric            ProductRelease = getProductRelease(M),
1398*5f757f3fSDimitry Andric            ProductPatch = getProductPatch(M);
1399*5f757f3fSDimitry Andric 
1400*5f757f3fSDimitry Andric   SmallString<7> Version; // 6 + null
1401*5f757f3fSDimitry Andric   raw_svector_ostream ostr(Version);
1402*5f757f3fSDimitry Andric   ostr << formatv("{0,0-2:d}{1,0-2:d}{2,0-2:d}", ProductVersion, ProductRelease,
1403*5f757f3fSDimitry Andric                   ProductPatch);
1404*5f757f3fSDimitry Andric 
1405*5f757f3fSDimitry Andric   // Drop 0 during conversion.
1406*5f757f3fSDimitry Andric   SmallString<sizeof(CompilationTime) - 1> CompilationTimeStr;
1407*5f757f3fSDimitry Andric   SmallString<sizeof(Version) - 1> VersionStr;
1408*5f757f3fSDimitry Andric 
1409*5f757f3fSDimitry Andric   ConverterEBCDIC::convertToEBCDIC(CompilationTime, CompilationTimeStr);
1410*5f757f3fSDimitry Andric   ConverterEBCDIC::convertToEBCDIC(Version, VersionStr);
1411*5f757f3fSDimitry Andric 
1412*5f757f3fSDimitry Andric   enum class PPA2MemberId : uint8_t {
1413*5f757f3fSDimitry Andric     // See z/OS Language Environment Vendor Interfaces v2r5, p.23, for
1414*5f757f3fSDimitry Andric     // complete list. Only the C runtime is supported by this backend.
1415*5f757f3fSDimitry Andric     LE_C_Runtime = 3,
1416*5f757f3fSDimitry Andric   };
1417*5f757f3fSDimitry Andric   enum class PPA2MemberSubId : uint8_t {
1418*5f757f3fSDimitry Andric     // List of languages using the LE C runtime implementation.
1419*5f757f3fSDimitry Andric     C = 0x00,
1420*5f757f3fSDimitry Andric     CXX = 0x01,
1421*5f757f3fSDimitry Andric     Swift = 0x03,
1422*5f757f3fSDimitry Andric     Go = 0x60,
1423*5f757f3fSDimitry Andric     LLVMBasedLang = 0xe7,
1424*5f757f3fSDimitry Andric   };
1425*5f757f3fSDimitry Andric   // PPA2 Flags
1426*5f757f3fSDimitry Andric   enum class PPA2Flags : uint8_t {
1427*5f757f3fSDimitry Andric     CompileForBinaryFloatingPoint = 0x80,
1428*5f757f3fSDimitry Andric     CompiledWithXPLink = 0x01,
1429*5f757f3fSDimitry Andric     CompiledUnitASCII = 0x04,
1430*5f757f3fSDimitry Andric     HasServiceInfo = 0x20,
1431*5f757f3fSDimitry Andric   };
1432*5f757f3fSDimitry Andric 
1433*5f757f3fSDimitry Andric   PPA2MemberSubId MemberSubId = PPA2MemberSubId::LLVMBasedLang;
1434*5f757f3fSDimitry Andric   if (auto *MD = M.getModuleFlag("zos_cu_language")) {
1435*5f757f3fSDimitry Andric     StringRef Language = cast<MDString>(MD)->getString();
1436*5f757f3fSDimitry Andric     MemberSubId = StringSwitch<PPA2MemberSubId>(Language)
1437*5f757f3fSDimitry Andric                       .Case("C", PPA2MemberSubId::C)
1438*5f757f3fSDimitry Andric                       .Case("C++", PPA2MemberSubId::CXX)
1439*5f757f3fSDimitry Andric                       .Case("Swift", PPA2MemberSubId::Swift)
1440*5f757f3fSDimitry Andric                       .Case("Go", PPA2MemberSubId::Go)
1441*5f757f3fSDimitry Andric                       .Default(PPA2MemberSubId::LLVMBasedLang);
1442*5f757f3fSDimitry Andric   }
1443*5f757f3fSDimitry Andric 
1444*5f757f3fSDimitry Andric   // Emit PPA2 section.
1445*5f757f3fSDimitry Andric   OutStreamer->emitLabel(PPA2Sym);
1446*5f757f3fSDimitry Andric   OutStreamer->emitInt8(static_cast<uint8_t>(PPA2MemberId::LE_C_Runtime));
1447*5f757f3fSDimitry Andric   OutStreamer->emitInt8(static_cast<uint8_t>(MemberSubId));
1448*5f757f3fSDimitry Andric   OutStreamer->emitInt8(0x22); // Member defined, c370_plist+c370_env
1449*5f757f3fSDimitry Andric   OutStreamer->emitInt8(0x04); // Control level 4 (XPLink)
1450*5f757f3fSDimitry Andric   OutStreamer->emitAbsoluteSymbolDiff(CELQSTRT, PPA2Sym, 4);
1451*5f757f3fSDimitry Andric   OutStreamer->emitInt32(0x00000000);
1452*5f757f3fSDimitry Andric   OutStreamer->emitAbsoluteSymbolDiff(DateVersionSym, PPA2Sym, 4);
1453*5f757f3fSDimitry Andric   OutStreamer->emitInt32(
1454*5f757f3fSDimitry Andric       0x00000000); // Offset to main entry point, always 0 (so says TR).
1455*5f757f3fSDimitry Andric   uint8_t Flgs = static_cast<uint8_t>(PPA2Flags::CompileForBinaryFloatingPoint);
1456*5f757f3fSDimitry Andric   Flgs |= static_cast<uint8_t>(PPA2Flags::CompiledWithXPLink);
1457*5f757f3fSDimitry Andric 
1458*5f757f3fSDimitry Andric   if (auto *MD = M.getModuleFlag("zos_le_char_mode")) {
1459*5f757f3fSDimitry Andric     const StringRef &CharMode = cast<MDString>(MD)->getString();
1460*5f757f3fSDimitry Andric     if (CharMode == "ascii") {
1461*5f757f3fSDimitry Andric       Flgs |= static_cast<uint8_t>(
1462*5f757f3fSDimitry Andric           PPA2Flags::CompiledUnitASCII); // Setting bit for ASCII char. mode.
1463*5f757f3fSDimitry Andric     } else if (CharMode != "ebcdic") {
1464*5f757f3fSDimitry Andric       report_fatal_error(
1465*5f757f3fSDimitry Andric           "Only ascii or ebcdic are valid values for zos_le_char_mode "
1466*5f757f3fSDimitry Andric           "metadata");
1467*5f757f3fSDimitry Andric     }
1468*5f757f3fSDimitry Andric   }
1469*5f757f3fSDimitry Andric 
1470*5f757f3fSDimitry Andric   OutStreamer->emitInt8(Flgs);
1471*5f757f3fSDimitry Andric   OutStreamer->emitInt8(0x00);    // Reserved.
1472*5f757f3fSDimitry Andric                                   // No MD5 signature before timestamp.
1473*5f757f3fSDimitry Andric                                   // No FLOAT(AFP(VOLATILE)).
1474*5f757f3fSDimitry Andric                                   // Remaining 5 flag bits reserved.
1475*5f757f3fSDimitry Andric   OutStreamer->emitInt16(0x0000); // 16 Reserved flag bits.
1476*5f757f3fSDimitry Andric 
1477*5f757f3fSDimitry Andric   // Emit date and version section.
1478*5f757f3fSDimitry Andric   OutStreamer->emitLabel(DateVersionSym);
1479*5f757f3fSDimitry Andric   OutStreamer->emitBytes(CompilationTimeStr.str());
1480*5f757f3fSDimitry Andric   OutStreamer->emitBytes(VersionStr.str());
1481*5f757f3fSDimitry Andric 
1482*5f757f3fSDimitry Andric   OutStreamer->emitInt16(0x0000); // Service level string length.
1483*5f757f3fSDimitry Andric 
1484*5f757f3fSDimitry Andric   // Emit 8 byte alignment.
1485*5f757f3fSDimitry Andric   // Emit pointer to PPA2 label.
1486*5f757f3fSDimitry Andric   OutStreamer->AddComment("A(PPA2-CELQSTRT)");
1487*5f757f3fSDimitry Andric   OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CELQSTRT, 8);
1488*5f757f3fSDimitry Andric   OutStreamer->popSection();
1489*5f757f3fSDimitry Andric }
1490*5f757f3fSDimitry Andric 
149104eeddc0SDimitry Andric void SystemZAsmPrinter::emitFunctionEntryLabel() {
149281ad6265SDimitry Andric   const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
149304eeddc0SDimitry Andric 
149404eeddc0SDimitry Andric   if (Subtarget.getTargetTriple().isOSzOS()) {
149504eeddc0SDimitry Andric     MCContext &OutContext = OutStreamer->getContext();
149681ad6265SDimitry Andric 
149781ad6265SDimitry Andric     // Save information for later use.
149881ad6265SDimitry Andric     std::string N(MF->getFunction().hasName()
149981ad6265SDimitry Andric                       ? Twine(MF->getFunction().getName()).concat("_").str()
150081ad6265SDimitry Andric                       : "");
150181ad6265SDimitry Andric 
150281ad6265SDimitry Andric     CurrentFnEPMarkerSym =
150381ad6265SDimitry Andric         OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true);
150481ad6265SDimitry Andric     CurrentFnPPA1Sym =
150581ad6265SDimitry Andric         OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true);
150604eeddc0SDimitry Andric 
150704eeddc0SDimitry Andric     // EntryPoint Marker
150804eeddc0SDimitry Andric     const MachineFrameInfo &MFFrame = MF->getFrameInfo();
150904eeddc0SDimitry Andric     bool IsUsingAlloca = MFFrame.hasVarSizedObjects();
1510*5f757f3fSDimitry Andric     uint32_t DSASize = MFFrame.getStackSize();
1511*5f757f3fSDimitry Andric     bool IsLeaf = DSASize == 0 && MFFrame.getCalleeSavedInfo().empty();
151204eeddc0SDimitry Andric 
1513*5f757f3fSDimitry Andric     // Set Flags.
151404eeddc0SDimitry Andric     uint8_t Flags = 0;
1515*5f757f3fSDimitry Andric     if (IsLeaf)
1516*5f757f3fSDimitry Andric       Flags |= 0x08;
151704eeddc0SDimitry Andric     if (IsUsingAlloca)
151804eeddc0SDimitry Andric       Flags |= 0x04;
151904eeddc0SDimitry Andric 
152004eeddc0SDimitry Andric     // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.
152104eeddc0SDimitry Andric     uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5
152204eeddc0SDimitry Andric     DSAAndFlags |= Flags;
152304eeddc0SDimitry Andric 
152404eeddc0SDimitry Andric     // Emit entry point marker section.
152504eeddc0SDimitry Andric     OutStreamer->AddComment("XPLINK Routine Layout Entry");
152681ad6265SDimitry Andric     OutStreamer->emitLabel(CurrentFnEPMarkerSym);
152704eeddc0SDimitry Andric     OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
152804eeddc0SDimitry Andric     OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
152904eeddc0SDimitry Andric     OutStreamer->AddComment("Mark Type C'1'");
153004eeddc0SDimitry Andric     OutStreamer->emitInt8(0xF1); // Mark Type.
153181ad6265SDimitry Andric     OutStreamer->AddComment("Offset to PPA1");
153281ad6265SDimitry Andric     OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym,
153381ad6265SDimitry Andric                                         4);
153404eeddc0SDimitry Andric     if (OutStreamer->isVerboseAsm()) {
153504eeddc0SDimitry Andric       OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
153604eeddc0SDimitry Andric       OutStreamer->AddComment("Entry Flags");
1537*5f757f3fSDimitry Andric       if (Flags & 0x08)
1538*5f757f3fSDimitry Andric         OutStreamer->AddComment("  Bit 1: 1 = Leaf function");
1539*5f757f3fSDimitry Andric       else
1540*5f757f3fSDimitry Andric         OutStreamer->AddComment("  Bit 1: 0 = Non-leaf function");
154104eeddc0SDimitry Andric       if (Flags & 0x04)
154204eeddc0SDimitry Andric         OutStreamer->AddComment("  Bit 2: 1 = Uses alloca");
154304eeddc0SDimitry Andric       else
154404eeddc0SDimitry Andric         OutStreamer->AddComment("  Bit 2: 0 = Does not use alloca");
154504eeddc0SDimitry Andric     }
154604eeddc0SDimitry Andric     OutStreamer->emitInt32(DSAAndFlags);
154704eeddc0SDimitry Andric   }
154804eeddc0SDimitry Andric 
154904eeddc0SDimitry Andric   AsmPrinter::emitFunctionEntryLabel();
155004eeddc0SDimitry Andric }
155104eeddc0SDimitry Andric 
15520b57cec5SDimitry Andric // Force static initialization.
1553480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() {
15540b57cec5SDimitry Andric   RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
15550b57cec5SDimitry Andric }
1556