xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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"
25*0fca6ea1SDimitry Andric #include "llvm/IR/Module.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCInstBuilder.h"
28480093f4SDimitry Andric #include "llvm/MC/MCSectionELF.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
30349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
315f757f3fSDimitry Andric #include "llvm/Support/Chrono.h"
325f757f3fSDimitry Andric #include "llvm/Support/ConvertEBCDIC.h"
335f757f3fSDimitry Andric #include "llvm/Support/FormatProviders.h"
345f757f3fSDimitry Andric #include "llvm/Support/FormatVariadic.h"
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric using namespace llvm;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the
390b57cec5SDimitry Andric // GR64 register operands turned into GR32s.
400b57cec5SDimitry Andric static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) {
410b57cec5SDimitry Andric   if (MI->isCompare())
420b57cec5SDimitry Andric     return MCInstBuilder(Opcode)
430b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
440b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm());
450b57cec5SDimitry Andric   else
460b57cec5SDimitry Andric     return MCInstBuilder(Opcode)
470b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
480b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg()))
490b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm());
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the
530b57cec5SDimitry Andric // GR64 register operands turned into GRH32s.
540b57cec5SDimitry Andric static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) {
550b57cec5SDimitry Andric   if (MI->isCompare())
560b57cec5SDimitry Andric     return MCInstBuilder(Opcode)
570b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
580b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm());
590b57cec5SDimitry Andric   else
600b57cec5SDimitry Andric     return MCInstBuilder(Opcode)
610b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
620b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg()))
630b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm());
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
660b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the
670b57cec5SDimitry Andric // R2 register turned into a GR64.
680b57cec5SDimitry Andric static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) {
690b57cec5SDimitry Andric   return MCInstBuilder(Opcode)
700b57cec5SDimitry Andric     .addReg(MI->getOperand(0).getReg())
710b57cec5SDimitry Andric     .addReg(MI->getOperand(1).getReg())
720b57cec5SDimitry Andric     .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()))
730b57cec5SDimitry Andric     .addImm(MI->getOperand(3).getImm())
740b57cec5SDimitry Andric     .addImm(MI->getOperand(4).getImm())
750b57cec5SDimitry Andric     .addImm(MI->getOperand(5).getImm());
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) {
790b57cec5SDimitry Andric   StringRef Name = "__tls_get_offset";
800b57cec5SDimitry Andric   return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
810b57cec5SDimitry Andric                                  MCSymbolRefExpr::VK_PLT,
820b57cec5SDimitry Andric                                  Context);
830b57cec5SDimitry Andric }
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) {
860b57cec5SDimitry Andric   StringRef Name = "_GLOBAL_OFFSET_TABLE_";
870b57cec5SDimitry Andric   return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name),
880b57cec5SDimitry Andric                                  MCSymbolRefExpr::VK_None,
890b57cec5SDimitry Andric                                  Context);
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric 
920b57cec5SDimitry Andric // MI is an instruction that accepts an optional alignment hint,
930b57cec5SDimitry Andric // and which was already lowered to LoweredMI.  If the alignment
940b57cec5SDimitry Andric // of the original memory operand is known, update LoweredMI to
950b57cec5SDimitry Andric // an instruction with the corresponding hint set.
960b57cec5SDimitry Andric static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI,
970b57cec5SDimitry Andric                                unsigned Opcode) {
9881ad6265SDimitry Andric   if (MI->memoperands_empty())
990b57cec5SDimitry Andric     return;
10081ad6265SDimitry Andric 
10181ad6265SDimitry Andric   Align Alignment = Align(16);
10281ad6265SDimitry Andric   for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(),
10381ad6265SDimitry Andric          EE = MI->memoperands_end(); MMOI != EE; ++MMOI)
10481ad6265SDimitry Andric     if ((*MMOI)->getAlign() < Alignment)
10581ad6265SDimitry Andric       Alignment = (*MMOI)->getAlign();
10681ad6265SDimitry Andric 
1070b57cec5SDimitry Andric   unsigned AlignmentHint = 0;
10881ad6265SDimitry Andric   if (Alignment >= Align(16))
1090b57cec5SDimitry Andric     AlignmentHint = 4;
11081ad6265SDimitry Andric   else if (Alignment >= Align(8))
1110b57cec5SDimitry Andric     AlignmentHint = 3;
1120b57cec5SDimitry Andric   if (AlignmentHint == 0)
1130b57cec5SDimitry Andric     return;
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   LoweredMI.setOpcode(Opcode);
1160b57cec5SDimitry Andric   LoweredMI.addOperand(MCOperand::createImm(AlignmentHint));
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric // MI loads the high part of a vector from memory.  Return an instruction
1200b57cec5SDimitry Andric // that uses replicating vector load Opcode to do the same thing.
1210b57cec5SDimitry Andric static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) {
1220b57cec5SDimitry Andric   return MCInstBuilder(Opcode)
1230b57cec5SDimitry Andric     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
1240b57cec5SDimitry Andric     .addReg(MI->getOperand(1).getReg())
1250b57cec5SDimitry Andric     .addImm(MI->getOperand(2).getImm())
1260b57cec5SDimitry Andric     .addReg(MI->getOperand(3).getReg());
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric // MI stores the high part of a vector to memory.  Return an instruction
1300b57cec5SDimitry Andric // that uses elemental vector store Opcode to do the same thing.
1310b57cec5SDimitry Andric static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) {
1320b57cec5SDimitry Andric   return MCInstBuilder(Opcode)
1330b57cec5SDimitry Andric     .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
1340b57cec5SDimitry Andric     .addReg(MI->getOperand(1).getReg())
1350b57cec5SDimitry Andric     .addImm(MI->getOperand(2).getImm())
1360b57cec5SDimitry Andric     .addReg(MI->getOperand(3).getReg())
1370b57cec5SDimitry Andric     .addImm(0);
1380b57cec5SDimitry Andric }
1390b57cec5SDimitry Andric 
14081ad6265SDimitry Andric // The XPLINK ABI requires that a no-op encoding the call type is emitted after
14181ad6265SDimitry Andric // each call to a subroutine. This information can be used by the called
14281ad6265SDimitry Andric // function to determine its entry point, e.g. for generating a backtrace. The
14381ad6265SDimitry Andric // call type is encoded as a register number in the bcr instruction. See
14481ad6265SDimitry Andric // enumeration CallType for the possible values.
14581ad6265SDimitry Andric void SystemZAsmPrinter::emitCallInformation(CallType CT) {
14681ad6265SDimitry Andric   EmitToStreamer(*OutStreamer,
14781ad6265SDimitry Andric                  MCInstBuilder(SystemZ::BCRAsm)
14881ad6265SDimitry Andric                      .addImm(0)
14981ad6265SDimitry Andric                      .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)]));
15081ad6265SDimitry Andric }
15181ad6265SDimitry Andric 
15206c3fb27SDimitry Andric uint32_t SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MCSymbol *Sym,
15306c3fb27SDimitry Andric                                                             unsigned SlotKind) {
15406c3fb27SDimitry Andric   auto Key = std::make_pair(Sym, SlotKind);
15506c3fb27SDimitry Andric   auto It = Displacements.find(Key);
15606c3fb27SDimitry Andric 
15706c3fb27SDimitry Andric   if (It != Displacements.end())
15806c3fb27SDimitry Andric     return (*It).second;
15906c3fb27SDimitry Andric 
16006c3fb27SDimitry Andric   // Determine length of descriptor.
16106c3fb27SDimitry Andric   uint32_t Length;
16206c3fb27SDimitry Andric   switch (SlotKind) {
16306c3fb27SDimitry Andric   case SystemZII::MO_ADA_DIRECT_FUNC_DESC:
16406c3fb27SDimitry Andric     Length = 2 * PointerSize;
16506c3fb27SDimitry Andric     break;
16606c3fb27SDimitry Andric   default:
16706c3fb27SDimitry Andric     Length = PointerSize;
16806c3fb27SDimitry Andric     break;
16906c3fb27SDimitry Andric   }
17006c3fb27SDimitry Andric 
17106c3fb27SDimitry Andric   uint32_t Displacement = NextDisplacement;
17206c3fb27SDimitry Andric   Displacements[std::make_pair(Sym, SlotKind)] = NextDisplacement;
17306c3fb27SDimitry Andric   NextDisplacement += Length;
17406c3fb27SDimitry Andric 
17506c3fb27SDimitry Andric   return Displacement;
17606c3fb27SDimitry Andric }
17706c3fb27SDimitry Andric 
17806c3fb27SDimitry Andric uint32_t
17906c3fb27SDimitry Andric SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MachineOperand MO) {
18006c3fb27SDimitry Andric   MCSymbol *Sym;
18106c3fb27SDimitry Andric   if (MO.getType() == MachineOperand::MO_GlobalAddress) {
18206c3fb27SDimitry Andric     const GlobalValue *GV = MO.getGlobal();
18306c3fb27SDimitry Andric     Sym = MO.getParent()->getMF()->getTarget().getSymbol(GV);
18406c3fb27SDimitry Andric     assert(Sym && "No symbol");
18506c3fb27SDimitry Andric   } else if (MO.getType() == MachineOperand::MO_ExternalSymbol) {
18606c3fb27SDimitry Andric     const char *SymName = MO.getSymbolName();
18706c3fb27SDimitry Andric     Sym = MO.getParent()->getMF()->getContext().getOrCreateSymbol(SymName);
18806c3fb27SDimitry Andric     assert(Sym && "No symbol");
18906c3fb27SDimitry Andric   } else
19006c3fb27SDimitry Andric     llvm_unreachable("Unexpected operand type");
19106c3fb27SDimitry Andric 
19206c3fb27SDimitry Andric   unsigned ADAslotType = MO.getTargetFlags();
19306c3fb27SDimitry Andric   return insert(Sym, ADAslotType);
19406c3fb27SDimitry Andric }
19506c3fb27SDimitry Andric 
1965ffd83dbSDimitry Andric void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) {
197753f127fSDimitry Andric   SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(),
198753f127fSDimitry Andric                                           getSubtargetInfo().getFeatureBits());
199753f127fSDimitry Andric 
2000b57cec5SDimitry Andric   SystemZMCInstLower Lower(MF->getContext(), *this);
2010b57cec5SDimitry Andric   MCInst LoweredMI;
2020b57cec5SDimitry Andric   switch (MI->getOpcode()) {
2030b57cec5SDimitry Andric   case SystemZ::Return:
20481ad6265SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BR)
20581ad6265SDimitry Andric       .addReg(SystemZ::R14D);
20681ad6265SDimitry Andric     break;
20781ad6265SDimitry Andric 
20881ad6265SDimitry Andric   case SystemZ::Return_XPLINK:
20981ad6265SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::B)
21081ad6265SDimitry Andric       .addReg(SystemZ::R7D)
21181ad6265SDimitry Andric       .addImm(2)
21281ad6265SDimitry Andric       .addReg(0);
2130b57cec5SDimitry Andric     break;
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   case SystemZ::CondReturn:
2160b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BCR)
2170b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
2180b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2190b57cec5SDimitry Andric       .addReg(SystemZ::R14D);
2200b57cec5SDimitry Andric     break;
2210b57cec5SDimitry Andric 
22281ad6265SDimitry Andric   case SystemZ::CondReturn_XPLINK:
22381ad6265SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BC)
22481ad6265SDimitry Andric       .addImm(MI->getOperand(0).getImm())
22581ad6265SDimitry Andric       .addImm(MI->getOperand(1).getImm())
22681ad6265SDimitry Andric       .addReg(SystemZ::R7D)
22781ad6265SDimitry Andric       .addImm(2)
22881ad6265SDimitry Andric       .addReg(0);
22981ad6265SDimitry Andric     break;
23081ad6265SDimitry Andric 
2310b57cec5SDimitry Andric   case SystemZ::CRBReturn:
2320b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CRB)
2330b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2340b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
2350b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2360b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2370b57cec5SDimitry Andric       .addImm(0);
2380b57cec5SDimitry Andric     break;
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric   case SystemZ::CGRBReturn:
2410b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGRB)
2420b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2430b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
2440b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2450b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2460b57cec5SDimitry Andric       .addImm(0);
2470b57cec5SDimitry Andric     break;
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric   case SystemZ::CIBReturn:
2500b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CIB)
2510b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2520b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2530b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2540b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2550b57cec5SDimitry Andric       .addImm(0);
2560b57cec5SDimitry Andric     break;
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   case SystemZ::CGIBReturn:
2590b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGIB)
2600b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2610b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2620b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2630b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2640b57cec5SDimitry Andric       .addImm(0);
2650b57cec5SDimitry Andric     break;
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric   case SystemZ::CLRBReturn:
2680b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLRB)
2690b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2700b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
2710b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2720b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2730b57cec5SDimitry Andric       .addImm(0);
2740b57cec5SDimitry Andric     break;
2750b57cec5SDimitry Andric 
2760b57cec5SDimitry Andric   case SystemZ::CLGRBReturn:
2770b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
2780b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2790b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
2800b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2810b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2820b57cec5SDimitry Andric       .addImm(0);
2830b57cec5SDimitry Andric     break;
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric   case SystemZ::CLIBReturn:
2860b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLIB)
2870b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2880b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2890b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2900b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
2910b57cec5SDimitry Andric       .addImm(0);
2920b57cec5SDimitry Andric     break;
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric   case SystemZ::CLGIBReturn:
2950b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
2960b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
2970b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
2980b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
2990b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
3000b57cec5SDimitry Andric       .addImm(0);
3010b57cec5SDimitry Andric     break;
3020b57cec5SDimitry Andric 
303fe6060f1SDimitry Andric   case SystemZ::CallBRASL_XPLINK64:
304fe6060f1SDimitry Andric     EmitToStreamer(*OutStreamer,
305fe6060f1SDimitry Andric                    MCInstBuilder(SystemZ::BRASL)
306fe6060f1SDimitry Andric                        .addReg(SystemZ::R7D)
307fe6060f1SDimitry Andric                        .addExpr(Lower.getExpr(MI->getOperand(0),
308fe6060f1SDimitry Andric                                               MCSymbolRefExpr::VK_PLT)));
30981ad6265SDimitry Andric     emitCallInformation(CallType::BRASL7);
310fe6060f1SDimitry Andric     return;
311fe6060f1SDimitry Andric 
312fe6060f1SDimitry Andric   case SystemZ::CallBASR_XPLINK64:
313fe6060f1SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
314fe6060f1SDimitry Andric                                      .addReg(SystemZ::R7D)
315fe6060f1SDimitry Andric                                      .addReg(MI->getOperand(0).getReg()));
31681ad6265SDimitry Andric     emitCallInformation(CallType::BASR76);
31781ad6265SDimitry Andric     return;
31881ad6265SDimitry Andric 
31981ad6265SDimitry Andric   case SystemZ::CallBASR_STACKEXT:
32081ad6265SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
32181ad6265SDimitry Andric                                      .addReg(SystemZ::R3D)
32281ad6265SDimitry Andric                                      .addReg(MI->getOperand(0).getReg()));
32381ad6265SDimitry Andric     emitCallInformation(CallType::BASR33);
324fe6060f1SDimitry Andric     return;
325fe6060f1SDimitry Andric 
32606c3fb27SDimitry Andric   case SystemZ::ADA_ENTRY_VALUE:
32706c3fb27SDimitry Andric   case SystemZ::ADA_ENTRY: {
32806c3fb27SDimitry Andric     const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
32906c3fb27SDimitry Andric     const SystemZInstrInfo *TII = Subtarget.getInstrInfo();
33006c3fb27SDimitry Andric     uint32_t Disp = ADATable.insert(MI->getOperand(1));
33106c3fb27SDimitry Andric     Register TargetReg = MI->getOperand(0).getReg();
33206c3fb27SDimitry Andric 
33306c3fb27SDimitry Andric     Register ADAReg = MI->getOperand(2).getReg();
33406c3fb27SDimitry Andric     Disp += MI->getOperand(3).getImm();
33506c3fb27SDimitry Andric     bool LoadAddr = MI->getOpcode() == SystemZ::ADA_ENTRY;
33606c3fb27SDimitry Andric 
33706c3fb27SDimitry Andric     unsigned Op0 = LoadAddr ? SystemZ::LA : SystemZ::LG;
33806c3fb27SDimitry Andric     unsigned Op = TII->getOpcodeForOffset(Op0, Disp);
33906c3fb27SDimitry Andric 
34006c3fb27SDimitry Andric     Register IndexReg = 0;
34106c3fb27SDimitry Andric     if (!Op) {
34206c3fb27SDimitry Andric       if (TargetReg != ADAReg) {
34306c3fb27SDimitry Andric         IndexReg = TargetReg;
34406c3fb27SDimitry Andric         // Use TargetReg to store displacement.
34506c3fb27SDimitry Andric         EmitToStreamer(
34606c3fb27SDimitry Andric             *OutStreamer,
34706c3fb27SDimitry Andric             MCInstBuilder(SystemZ::LLILF).addReg(TargetReg).addImm(Disp));
34806c3fb27SDimitry Andric       } else
34906c3fb27SDimitry Andric         EmitToStreamer(
35006c3fb27SDimitry Andric             *OutStreamer,
35106c3fb27SDimitry Andric             MCInstBuilder(SystemZ::ALGFI).addReg(TargetReg).addImm(Disp));
35206c3fb27SDimitry Andric       Disp = 0;
35306c3fb27SDimitry Andric       Op = Op0;
35406c3fb27SDimitry Andric     }
35506c3fb27SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(Op)
35606c3fb27SDimitry Andric                                      .addReg(TargetReg)
3575f757f3fSDimitry Andric                                      .addReg(ADAReg)
35806c3fb27SDimitry Andric                                      .addImm(Disp)
3595f757f3fSDimitry Andric                                      .addReg(IndexReg));
36006c3fb27SDimitry Andric 
36106c3fb27SDimitry Andric     return;
36206c3fb27SDimitry Andric   }
3630b57cec5SDimitry Andric   case SystemZ::CallBRASL:
3640b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRASL)
3650b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
3660b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
3670b57cec5SDimitry Andric     break;
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric   case SystemZ::CallBASR:
3700b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BASR)
3710b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
3720b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg());
3730b57cec5SDimitry Andric     break;
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric   case SystemZ::CallJG:
3760b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::JG)
3770b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT));
3780b57cec5SDimitry Andric     break;
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric   case SystemZ::CallBRCL:
3810b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRCL)
3820b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
3830b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
3840b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT));
3850b57cec5SDimitry Andric     break;
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   case SystemZ::CallBR:
388e8d8bef9SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BR)
389e8d8bef9SDimitry Andric       .addReg(MI->getOperand(0).getReg());
3900b57cec5SDimitry Andric     break;
3910b57cec5SDimitry Andric 
3920b57cec5SDimitry Andric   case SystemZ::CallBCR:
3930b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BCR)
3940b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
3950b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
396e8d8bef9SDimitry Andric       .addReg(MI->getOperand(2).getReg());
3970b57cec5SDimitry Andric     break;
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric   case SystemZ::CRBCall:
4000b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CRB)
4010b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4020b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
4030b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
404e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4050b57cec5SDimitry Andric       .addImm(0);
4060b57cec5SDimitry Andric     break;
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric   case SystemZ::CGRBCall:
4090b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGRB)
4100b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4110b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
4120b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
413e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4140b57cec5SDimitry Andric       .addImm(0);
4150b57cec5SDimitry Andric     break;
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   case SystemZ::CIBCall:
4180b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CIB)
4190b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4200b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
4210b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
422e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4230b57cec5SDimitry Andric       .addImm(0);
4240b57cec5SDimitry Andric     break;
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric   case SystemZ::CGIBCall:
4270b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CGIB)
4280b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4290b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
4300b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
431e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4320b57cec5SDimitry Andric       .addImm(0);
4330b57cec5SDimitry Andric     break;
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   case SystemZ::CLRBCall:
4360b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLRB)
4370b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4380b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
4390b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
440e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4410b57cec5SDimitry Andric       .addImm(0);
4420b57cec5SDimitry Andric     break;
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric   case SystemZ::CLGRBCall:
4450b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGRB)
4460b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4470b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
4480b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
449e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4500b57cec5SDimitry Andric       .addImm(0);
4510b57cec5SDimitry Andric     break;
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric   case SystemZ::CLIBCall:
4540b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLIB)
4550b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4560b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
4570b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
458e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4590b57cec5SDimitry Andric       .addImm(0);
4600b57cec5SDimitry Andric     break;
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric   case SystemZ::CLGIBCall:
4630b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::CLGIB)
4640b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4650b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
4660b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
467e8d8bef9SDimitry Andric       .addReg(MI->getOperand(3).getReg())
4680b57cec5SDimitry Andric       .addImm(0);
4690b57cec5SDimitry Andric     break;
4700b57cec5SDimitry Andric 
4710b57cec5SDimitry Andric   case SystemZ::TLS_GDCALL:
4720b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRASL)
4730b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
4740b57cec5SDimitry Andric       .addExpr(getTLSGetOffset(MF->getContext()))
4750b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD));
4760b57cec5SDimitry Andric     break;
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric   case SystemZ::TLS_LDCALL:
4790b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRASL)
4800b57cec5SDimitry Andric       .addReg(SystemZ::R14D)
4810b57cec5SDimitry Andric       .addExpr(getTLSGetOffset(MF->getContext()))
4820b57cec5SDimitry Andric       .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM));
4830b57cec5SDimitry Andric     break;
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric   case SystemZ::GOT:
4860b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::LARL)
4870b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
4880b57cec5SDimitry Andric       .addExpr(getGlobalOffsetTable(MF->getContext()));
4890b57cec5SDimitry Andric     break;
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric   case SystemZ::IILF64:
4920b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::IILF)
4930b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg()))
4940b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm());
4950b57cec5SDimitry Andric     break;
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric   case SystemZ::IIHF64:
4980b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::IIHF)
4990b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg()))
5000b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm());
5010b57cec5SDimitry Andric     break;
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric   case SystemZ::RISBHH:
5040b57cec5SDimitry Andric   case SystemZ::RISBHL:
5050b57cec5SDimitry Andric     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG);
5060b57cec5SDimitry Andric     break;
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric   case SystemZ::RISBLH:
5090b57cec5SDimitry Andric   case SystemZ::RISBLL:
5100b57cec5SDimitry Andric     LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG);
5110b57cec5SDimitry Andric     break;
5120b57cec5SDimitry Andric 
5130b57cec5SDimitry Andric   case SystemZ::VLVGP32:
5140b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLVGP)
5150b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
5160b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg()))
5170b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg()));
5180b57cec5SDimitry Andric     break;
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   case SystemZ::VLR32:
5210b57cec5SDimitry Andric   case SystemZ::VLR64:
5220b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLR)
5230b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
5240b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()));
5250b57cec5SDimitry Andric     break;
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric   case SystemZ::VL:
5280b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
5290b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign);
5300b57cec5SDimitry Andric     break;
5310b57cec5SDimitry Andric 
5320b57cec5SDimitry Andric   case SystemZ::VST:
5330b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
5340b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign);
5350b57cec5SDimitry Andric     break;
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric   case SystemZ::VLM:
5380b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
5390b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign);
5400b57cec5SDimitry Andric     break;
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric   case SystemZ::VSTM:
5430b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
5440b57cec5SDimitry Andric     lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign);
5450b57cec5SDimitry Andric     break;
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric   case SystemZ::VL32:
5480b57cec5SDimitry Andric     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF);
5490b57cec5SDimitry Andric     break;
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric   case SystemZ::VL64:
5520b57cec5SDimitry Andric     LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG);
5530b57cec5SDimitry Andric     break;
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric   case SystemZ::VST32:
5560b57cec5SDimitry Andric     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF);
5570b57cec5SDimitry Andric     break;
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric   case SystemZ::VST64:
5600b57cec5SDimitry Andric     LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG);
5610b57cec5SDimitry Andric     break;
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric   case SystemZ::LFER:
5640b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLGVF)
5650b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg()))
5660b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg()))
5670b57cec5SDimitry Andric       .addReg(0).addImm(0);
5680b57cec5SDimitry Andric     break;
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric   case SystemZ::LEFR:
5710b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::VLVGF)
5720b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
5730b57cec5SDimitry Andric       .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg()))
5740b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
5750b57cec5SDimitry Andric       .addReg(0).addImm(0);
5760b57cec5SDimitry Andric     break;
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric #define LOWER_LOW(NAME)                                                 \
5790b57cec5SDimitry Andric   case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break
5800b57cec5SDimitry Andric 
5810b57cec5SDimitry Andric   LOWER_LOW(IILL);
5820b57cec5SDimitry Andric   LOWER_LOW(IILH);
5830b57cec5SDimitry Andric   LOWER_LOW(TMLL);
5840b57cec5SDimitry Andric   LOWER_LOW(TMLH);
5850b57cec5SDimitry Andric   LOWER_LOW(NILL);
5860b57cec5SDimitry Andric   LOWER_LOW(NILH);
5870b57cec5SDimitry Andric   LOWER_LOW(NILF);
5880b57cec5SDimitry Andric   LOWER_LOW(OILL);
5890b57cec5SDimitry Andric   LOWER_LOW(OILH);
5900b57cec5SDimitry Andric   LOWER_LOW(OILF);
5910b57cec5SDimitry Andric   LOWER_LOW(XILF);
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric #undef LOWER_LOW
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric #define LOWER_HIGH(NAME) \
5960b57cec5SDimitry Andric   case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric   LOWER_HIGH(IIHL);
5990b57cec5SDimitry Andric   LOWER_HIGH(IIHH);
6000b57cec5SDimitry Andric   LOWER_HIGH(TMHL);
6010b57cec5SDimitry Andric   LOWER_HIGH(TMHH);
6020b57cec5SDimitry Andric   LOWER_HIGH(NIHL);
6030b57cec5SDimitry Andric   LOWER_HIGH(NIHH);
6040b57cec5SDimitry Andric   LOWER_HIGH(NIHF);
6050b57cec5SDimitry Andric   LOWER_HIGH(OIHL);
6060b57cec5SDimitry Andric   LOWER_HIGH(OIHH);
6070b57cec5SDimitry Andric   LOWER_HIGH(OIHF);
6080b57cec5SDimitry Andric   LOWER_HIGH(XIHF);
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric #undef LOWER_HIGH
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric   case SystemZ::Serialize:
6130b57cec5SDimitry Andric     if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization())
6140b57cec5SDimitry Andric       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
6150b57cec5SDimitry Andric         .addImm(14).addReg(SystemZ::R0D);
6160b57cec5SDimitry Andric     else
6170b57cec5SDimitry Andric       LoweredMI = MCInstBuilder(SystemZ::BCRAsm)
6180b57cec5SDimitry Andric         .addImm(15).addReg(SystemZ::R0D);
6190b57cec5SDimitry Andric     break;
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric   // We want to emit "j .+2" for traps, jumping to the relative immediate field
6220b57cec5SDimitry Andric   // of the jump instruction, which is an illegal instruction. We cannot emit a
6230b57cec5SDimitry Andric   // "." symbol, so create and emit a temp label before the instruction and use
6240b57cec5SDimitry Andric   // that instead.
6250b57cec5SDimitry Andric   case SystemZ::Trap: {
6260b57cec5SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
6275ffd83dbSDimitry Andric     OutStreamer->emitLabel(DotSym);
6280b57cec5SDimitry Andric 
6290b57cec5SDimitry Andric     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
6300b57cec5SDimitry Andric     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
6310b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::J)
6320b57cec5SDimitry Andric       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
6330b57cec5SDimitry Andric     }
6340b57cec5SDimitry Andric     break;
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric   // Conditional traps will create a branch on condition instruction that jumps
6370b57cec5SDimitry Andric   // to the relative immediate field of the jump instruction. (eg. "jo .+2")
6380b57cec5SDimitry Andric   case SystemZ::CondTrap: {
6390b57cec5SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
6405ffd83dbSDimitry Andric     OutStreamer->emitLabel(DotSym);
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric     const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext);
6430b57cec5SDimitry Andric     const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext);
6440b57cec5SDimitry Andric     LoweredMI = MCInstBuilder(SystemZ::BRC)
6450b57cec5SDimitry Andric       .addImm(MI->getOperand(0).getImm())
6460b57cec5SDimitry Andric       .addImm(MI->getOperand(1).getImm())
6470b57cec5SDimitry Andric       .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext));
6480b57cec5SDimitry Andric     }
6490b57cec5SDimitry Andric     break;
6500b57cec5SDimitry Andric 
6518bcb0991SDimitry Andric   case TargetOpcode::FENTRY_CALL:
6528bcb0991SDimitry Andric     LowerFENTRY_CALL(*MI, Lower);
6538bcb0991SDimitry Andric     return;
6548bcb0991SDimitry Andric 
6550b57cec5SDimitry Andric   case TargetOpcode::STACKMAP:
6560b57cec5SDimitry Andric     LowerSTACKMAP(*MI);
6570b57cec5SDimitry Andric     return;
6580b57cec5SDimitry Andric 
6590b57cec5SDimitry Andric   case TargetOpcode::PATCHPOINT:
6600b57cec5SDimitry Andric     LowerPATCHPOINT(*MI, Lower);
6610b57cec5SDimitry Andric     return;
6620b57cec5SDimitry Andric 
663fe6060f1SDimitry Andric   case SystemZ::EXRL_Pseudo: {
664fe6060f1SDimitry Andric     unsigned TargetInsOpc = MI->getOperand(0).getImm();
665fe6060f1SDimitry Andric     Register LenMinus1Reg = MI->getOperand(1).getReg();
666fe6060f1SDimitry Andric     Register DestReg = MI->getOperand(2).getReg();
667fe6060f1SDimitry Andric     int64_t DestDisp = MI->getOperand(3).getImm();
668fe6060f1SDimitry Andric     Register SrcReg = MI->getOperand(4).getReg();
669fe6060f1SDimitry Andric     int64_t SrcDisp = MI->getOperand(5).getImm();
670fe6060f1SDimitry Andric 
671349cc55cSDimitry Andric     SystemZTargetStreamer *TS = getTargetStreamer();
672fe6060f1SDimitry Andric     MCSymbol *DotSym = nullptr;
673fe6060f1SDimitry Andric     MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg)
674fe6060f1SDimitry Andric       .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp);
675349cc55cSDimitry Andric     SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget());
676349cc55cSDimitry Andric     SystemZTargetStreamer::EXRLT2SymMap::iterator I =
677349cc55cSDimitry Andric         TS->EXRLTargets2Sym.find(ET_STI);
678349cc55cSDimitry Andric     if (I != TS->EXRLTargets2Sym.end())
679fe6060f1SDimitry Andric       DotSym = I->second;
680fe6060f1SDimitry Andric     else
681349cc55cSDimitry Andric       TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol();
682fe6060f1SDimitry Andric     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
683fe6060f1SDimitry Andric     EmitToStreamer(
684fe6060f1SDimitry Andric         *OutStreamer,
685fe6060f1SDimitry Andric         MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot));
686fe6060f1SDimitry Andric     return;
687fe6060f1SDimitry Andric   }
688fe6060f1SDimitry Andric 
6890b57cec5SDimitry Andric   default:
6900b57cec5SDimitry Andric     Lower.lower(MI, LoweredMI);
6910b57cec5SDimitry Andric     break;
6920b57cec5SDimitry Andric   }
6930b57cec5SDimitry Andric   EmitToStreamer(*OutStreamer, LoweredMI);
6940b57cec5SDimitry Andric }
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric // Emit the largest nop instruction smaller than or equal to NumBytes
6970b57cec5SDimitry Andric // bytes.  Return the size of nop emitted.
6980b57cec5SDimitry Andric static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer,
6990b57cec5SDimitry Andric                         unsigned NumBytes, const MCSubtargetInfo &STI) {
7000b57cec5SDimitry Andric   if (NumBytes < 2) {
7010b57cec5SDimitry Andric     llvm_unreachable("Zero nops?");
7020b57cec5SDimitry Andric     return 0;
7030b57cec5SDimitry Andric   }
7040b57cec5SDimitry Andric   else if (NumBytes < 4) {
7055ffd83dbSDimitry Andric     OutStreamer.emitInstruction(
7065ffd83dbSDimitry Andric         MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI);
7070b57cec5SDimitry Andric     return 2;
7080b57cec5SDimitry Andric   }
7090b57cec5SDimitry Andric   else if (NumBytes < 6) {
7105ffd83dbSDimitry Andric     OutStreamer.emitInstruction(
7115ffd83dbSDimitry Andric         MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0),
7120b57cec5SDimitry Andric         STI);
7130b57cec5SDimitry Andric     return 4;
7140b57cec5SDimitry Andric   }
7150b57cec5SDimitry Andric   else {
7160b57cec5SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
7170b57cec5SDimitry Andric     const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext);
7185ffd83dbSDimitry Andric     OutStreamer.emitLabel(DotSym);
7195ffd83dbSDimitry Andric     OutStreamer.emitInstruction(
7205ffd83dbSDimitry Andric         MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI);
7210b57cec5SDimitry Andric     return 6;
7220b57cec5SDimitry Andric   }
7230b57cec5SDimitry Andric }
7240b57cec5SDimitry Andric 
7258bcb0991SDimitry Andric void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI,
7268bcb0991SDimitry Andric                                          SystemZMCInstLower &Lower) {
7278bcb0991SDimitry Andric   MCContext &Ctx = MF->getContext();
728480093f4SDimitry Andric   if (MF->getFunction().hasFnAttribute("mrecord-mcount")) {
729480093f4SDimitry Andric     MCSymbol *DotSym = OutContext.createTempSymbol();
73081ad6265SDimitry Andric     OutStreamer->pushSection();
73181ad6265SDimitry Andric     OutStreamer->switchSection(
732480093f4SDimitry Andric         Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC));
7335ffd83dbSDimitry Andric     OutStreamer->emitSymbolValue(DotSym, 8);
73481ad6265SDimitry Andric     OutStreamer->popSection();
7355ffd83dbSDimitry Andric     OutStreamer->emitLabel(DotSym);
736480093f4SDimitry Andric   }
737480093f4SDimitry Andric 
738480093f4SDimitry Andric   if (MF->getFunction().hasFnAttribute("mnop-mcount")) {
7398bcb0991SDimitry Andric     EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo());
7408bcb0991SDimitry Andric     return;
7418bcb0991SDimitry Andric   }
7428bcb0991SDimitry Andric 
7438bcb0991SDimitry Andric   MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__");
7448bcb0991SDimitry Andric   const MCSymbolRefExpr *Op =
7458bcb0991SDimitry Andric       MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx);
7465ffd83dbSDimitry Andric   OutStreamer->emitInstruction(
7475ffd83dbSDimitry Andric       MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op),
7485ffd83dbSDimitry Andric       getSubtargetInfo());
7498bcb0991SDimitry Andric }
7508bcb0991SDimitry Andric 
7510b57cec5SDimitry Andric void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) {
75281ad6265SDimitry Andric   auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo();
7530b57cec5SDimitry Andric 
7540b57cec5SDimitry Andric   unsigned NumNOPBytes = MI.getOperand(1).getImm();
7550b57cec5SDimitry Andric 
756480093f4SDimitry Andric   auto &Ctx = OutStreamer->getContext();
757480093f4SDimitry Andric   MCSymbol *MILabel = Ctx.createTempSymbol();
7585ffd83dbSDimitry Andric   OutStreamer->emitLabel(MILabel);
759480093f4SDimitry Andric 
760480093f4SDimitry Andric   SM.recordStackMap(*MILabel, MI);
7610b57cec5SDimitry Andric   assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!");
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric   // Scan ahead to trim the shadow.
7640b57cec5SDimitry Andric   unsigned ShadowBytes = 0;
7650b57cec5SDimitry Andric   const MachineBasicBlock &MBB = *MI.getParent();
7660b57cec5SDimitry Andric   MachineBasicBlock::const_iterator MII(MI);
7670b57cec5SDimitry Andric   ++MII;
7680b57cec5SDimitry Andric   while (ShadowBytes < NumNOPBytes) {
7690b57cec5SDimitry Andric     if (MII == MBB.end() ||
7700b57cec5SDimitry Andric         MII->getOpcode() == TargetOpcode::PATCHPOINT ||
7710b57cec5SDimitry Andric         MII->getOpcode() == TargetOpcode::STACKMAP)
7720b57cec5SDimitry Andric       break;
7730b57cec5SDimitry Andric     ShadowBytes += TII->getInstSizeInBytes(*MII);
7740b57cec5SDimitry Andric     if (MII->isCall())
7750b57cec5SDimitry Andric       break;
7760b57cec5SDimitry Andric     ++MII;
7770b57cec5SDimitry Andric   }
7780b57cec5SDimitry Andric 
7790b57cec5SDimitry Andric   // Emit nops.
7800b57cec5SDimitry Andric   while (ShadowBytes < NumNOPBytes)
7810b57cec5SDimitry Andric     ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes,
7820b57cec5SDimitry Andric                            getSubtargetInfo());
7830b57cec5SDimitry Andric }
7840b57cec5SDimitry Andric 
7850b57cec5SDimitry Andric // Lower a patchpoint of the form:
7860b57cec5SDimitry Andric // [<def>], <id>, <numBytes>, <target>, <numArgs>
7870b57cec5SDimitry Andric void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI,
7880b57cec5SDimitry Andric                                         SystemZMCInstLower &Lower) {
789480093f4SDimitry Andric   auto &Ctx = OutStreamer->getContext();
790480093f4SDimitry Andric   MCSymbol *MILabel = Ctx.createTempSymbol();
7915ffd83dbSDimitry Andric   OutStreamer->emitLabel(MILabel);
792480093f4SDimitry Andric 
793480093f4SDimitry Andric   SM.recordPatchPoint(*MILabel, MI);
7940b57cec5SDimitry Andric   PatchPointOpers Opers(&MI);
7950b57cec5SDimitry Andric 
7960b57cec5SDimitry Andric   unsigned EncodedBytes = 0;
7970b57cec5SDimitry Andric   const MachineOperand &CalleeMO = Opers.getCallTarget();
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric   if (CalleeMO.isImm()) {
8000b57cec5SDimitry Andric     uint64_t CallTarget = CalleeMO.getImm();
8010b57cec5SDimitry Andric     if (CallTarget) {
8020b57cec5SDimitry Andric       unsigned ScratchIdx = -1;
8030b57cec5SDimitry Andric       unsigned ScratchReg = 0;
8040b57cec5SDimitry Andric       do {
8050b57cec5SDimitry Andric         ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1);
8060b57cec5SDimitry Andric         ScratchReg = MI.getOperand(ScratchIdx).getReg();
8070b57cec5SDimitry Andric       } while (ScratchReg == SystemZ::R0D);
8080b57cec5SDimitry Andric 
8090b57cec5SDimitry Andric       // Materialize the call target address
8100b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF)
8110b57cec5SDimitry Andric                                       .addReg(ScratchReg)
8120b57cec5SDimitry Andric                                       .addImm(CallTarget & 0xFFFFFFFF));
8130b57cec5SDimitry Andric       EncodedBytes += 6;
8140b57cec5SDimitry Andric       if (CallTarget >> 32) {
8150b57cec5SDimitry Andric         EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF)
8160b57cec5SDimitry Andric                                         .addReg(ScratchReg)
8170b57cec5SDimitry Andric                                         .addImm(CallTarget >> 32));
8180b57cec5SDimitry Andric         EncodedBytes += 6;
8190b57cec5SDimitry Andric       }
8200b57cec5SDimitry Andric 
8210b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR)
8220b57cec5SDimitry Andric                                      .addReg(SystemZ::R14D)
8230b57cec5SDimitry Andric                                      .addReg(ScratchReg));
8240b57cec5SDimitry Andric       EncodedBytes += 2;
8250b57cec5SDimitry Andric     }
8260b57cec5SDimitry Andric   } else if (CalleeMO.isGlobal()) {
8270b57cec5SDimitry Andric     const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT);
8280b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL)
8290b57cec5SDimitry Andric                                    .addReg(SystemZ::R14D)
8300b57cec5SDimitry Andric                                    .addExpr(Expr));
8310b57cec5SDimitry Andric     EncodedBytes += 6;
8320b57cec5SDimitry Andric   }
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric   // Emit padding.
8350b57cec5SDimitry Andric   unsigned NumBytes = Opers.getNumPatchBytes();
8360b57cec5SDimitry Andric   assert(NumBytes >= EncodedBytes &&
8370b57cec5SDimitry Andric          "Patchpoint can't request size less than the length of a call.");
8380b57cec5SDimitry Andric   assert((NumBytes - EncodedBytes) % 2 == 0 &&
8390b57cec5SDimitry Andric          "Invalid number of NOP bytes requested!");
8400b57cec5SDimitry Andric   while (EncodedBytes < NumBytes)
8410b57cec5SDimitry Andric     EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes,
8420b57cec5SDimitry Andric                             getSubtargetInfo());
8430b57cec5SDimitry Andric }
8440b57cec5SDimitry Andric 
845bdd1243dSDimitry Andric // The *alignment* of 128-bit vector types is different between the software
846bdd1243dSDimitry Andric // and hardware vector ABIs. If the there is an externally visible use of a
847bdd1243dSDimitry Andric // vector type in the module it should be annotated with an attribute.
848bdd1243dSDimitry Andric void SystemZAsmPrinter::emitAttributes(Module &M) {
849bdd1243dSDimitry Andric   if (M.getModuleFlag("s390x-visible-vector-ABI")) {
850bdd1243dSDimitry Andric     bool HasVectorFeature =
85106c3fb27SDimitry Andric       TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureVector);
852bdd1243dSDimitry Andric     OutStreamer->emitGNUAttribute(8, HasVectorFeature ? 2 : 1);
853bdd1243dSDimitry Andric   }
854bdd1243dSDimitry Andric }
855bdd1243dSDimitry Andric 
8560b57cec5SDimitry Andric // Convert a SystemZ-specific constant pool modifier into the associated
8570b57cec5SDimitry Andric // MCSymbolRefExpr variant kind.
8580b57cec5SDimitry Andric static MCSymbolRefExpr::VariantKind
8590b57cec5SDimitry Andric getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) {
8600b57cec5SDimitry Andric   switch (Modifier) {
8610b57cec5SDimitry Andric   case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD;
8620b57cec5SDimitry Andric   case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM;
8630b57cec5SDimitry Andric   case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF;
8640b57cec5SDimitry Andric   case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF;
8650b57cec5SDimitry Andric   }
8660b57cec5SDimitry Andric   llvm_unreachable("Invalid SystemCPModifier!");
8670b57cec5SDimitry Andric }
8680b57cec5SDimitry Andric 
8695ffd83dbSDimitry Andric void SystemZAsmPrinter::emitMachineConstantPoolValue(
8705ffd83dbSDimitry Andric     MachineConstantPoolValue *MCPV) {
8710b57cec5SDimitry Andric   auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV);
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric   const MCExpr *Expr =
8740b57cec5SDimitry Andric     MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()),
8750b57cec5SDimitry Andric                             getModifierVariantKind(ZCPV->getModifier()),
8760b57cec5SDimitry Andric                             OutContext);
8770b57cec5SDimitry Andric   uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType());
8780b57cec5SDimitry Andric 
8795ffd83dbSDimitry Andric   OutStreamer->emitValue(Expr, Size);
8800b57cec5SDimitry Andric }
8810b57cec5SDimitry Andric 
882bdd1243dSDimitry Andric static void printFormattedRegName(const MCAsmInfo *MAI, unsigned RegNo,
883bdd1243dSDimitry Andric                                   raw_ostream &OS) {
884bdd1243dSDimitry Andric   const char *RegName = SystemZInstPrinter::getRegisterName(RegNo);
885bdd1243dSDimitry Andric   if (MAI->getAssemblerDialect() == AD_HLASM) {
886bdd1243dSDimitry Andric     // Skip register prefix so that only register number is left
887bdd1243dSDimitry Andric     assert(isalpha(RegName[0]) && isdigit(RegName[1]));
888bdd1243dSDimitry Andric     OS << (RegName + 1);
889bdd1243dSDimitry Andric   } else
890bdd1243dSDimitry Andric     OS << '%' << RegName;
891bdd1243dSDimitry Andric }
892bdd1243dSDimitry Andric 
893*0fca6ea1SDimitry Andric static void printReg(unsigned Reg, const MCAsmInfo *MAI, raw_ostream &OS) {
894*0fca6ea1SDimitry Andric   if (!Reg)
895bdd1243dSDimitry Andric     OS << '0';
896bdd1243dSDimitry Andric   else
897*0fca6ea1SDimitry Andric     printFormattedRegName(MAI, Reg, OS);
898*0fca6ea1SDimitry Andric }
899*0fca6ea1SDimitry Andric 
900*0fca6ea1SDimitry Andric static void printOperand(const MCOperand &MCOp, const MCAsmInfo *MAI,
901*0fca6ea1SDimitry Andric                          raw_ostream &OS) {
902*0fca6ea1SDimitry Andric   if (MCOp.isReg())
903*0fca6ea1SDimitry Andric     printReg(MCOp.getReg(), MAI, OS);
904*0fca6ea1SDimitry Andric   else if (MCOp.isImm())
905bdd1243dSDimitry Andric     OS << MCOp.getImm();
906bdd1243dSDimitry Andric   else if (MCOp.isExpr())
907bdd1243dSDimitry Andric     MCOp.getExpr()->print(OS, MAI);
908bdd1243dSDimitry Andric   else
909bdd1243dSDimitry Andric     llvm_unreachable("Invalid operand");
910bdd1243dSDimitry Andric }
911bdd1243dSDimitry Andric 
912bdd1243dSDimitry Andric static void printAddress(const MCAsmInfo *MAI, unsigned Base,
913bdd1243dSDimitry Andric                          const MCOperand &DispMO, unsigned Index,
914bdd1243dSDimitry Andric                          raw_ostream &OS) {
915bdd1243dSDimitry Andric   printOperand(DispMO, MAI, OS);
916bdd1243dSDimitry Andric   if (Base || Index) {
917bdd1243dSDimitry Andric     OS << '(';
918bdd1243dSDimitry Andric     if (Index) {
919bdd1243dSDimitry Andric       printFormattedRegName(MAI, Index, OS);
920bdd1243dSDimitry Andric       if (Base)
921bdd1243dSDimitry Andric         OS << ',';
922bdd1243dSDimitry Andric     }
923bdd1243dSDimitry Andric     if (Base)
924bdd1243dSDimitry Andric       printFormattedRegName(MAI, Base, OS);
925bdd1243dSDimitry Andric     OS << ')';
926bdd1243dSDimitry Andric   }
927bdd1243dSDimitry Andric }
928bdd1243dSDimitry Andric 
9290b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
9300b57cec5SDimitry Andric                                         const char *ExtraCode,
9310b57cec5SDimitry Andric                                         raw_ostream &OS) {
932fe6060f1SDimitry Andric   const MCRegisterInfo &MRI = *TM.getMCRegisterInfo();
933fe6060f1SDimitry Andric   const MachineOperand &MO = MI->getOperand(OpNo);
934fe6060f1SDimitry Andric   MCOperand MCOp;
935fe6060f1SDimitry Andric   if (ExtraCode) {
936fe6060f1SDimitry Andric     if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() &&
937fe6060f1SDimitry Andric         SystemZ::GR128BitRegClass.contains(MO.getReg()))
938fe6060f1SDimitry Andric       MCOp =
939fe6060f1SDimitry Andric           MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64));
940fe6060f1SDimitry Andric     else
9410b57cec5SDimitry Andric       return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS);
942fe6060f1SDimitry Andric   } else {
9430b57cec5SDimitry Andric     SystemZMCInstLower Lower(MF->getContext(), *this);
944fe6060f1SDimitry Andric     MCOp = Lower.lowerOperand(MO);
945fe6060f1SDimitry Andric   }
946bdd1243dSDimitry Andric   printOperand(MCOp, MAI, OS);
9470b57cec5SDimitry Andric   return false;
9480b57cec5SDimitry Andric }
9490b57cec5SDimitry Andric 
9500b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
9510b57cec5SDimitry Andric                                               unsigned OpNo,
9520b57cec5SDimitry Andric                                               const char *ExtraCode,
9530b57cec5SDimitry Andric                                               raw_ostream &OS) {
954*0fca6ea1SDimitry Andric   if (ExtraCode && ExtraCode[0] && !ExtraCode[1]) {
955*0fca6ea1SDimitry Andric     switch (ExtraCode[0]) {
956*0fca6ea1SDimitry Andric     case 'A':
957*0fca6ea1SDimitry Andric       // Unlike EmitMachineNode(), EmitSpecialNode(INLINEASM) does not call
958*0fca6ea1SDimitry Andric       // setMemRefs(), so MI->memoperands() is empty and the alignment
959*0fca6ea1SDimitry Andric       // information is not available.
960*0fca6ea1SDimitry Andric       return false;
961*0fca6ea1SDimitry Andric     case 'O':
962*0fca6ea1SDimitry Andric       OS << MI->getOperand(OpNo + 1).getImm();
963*0fca6ea1SDimitry Andric       return false;
964*0fca6ea1SDimitry Andric     case 'R':
965*0fca6ea1SDimitry Andric       ::printReg(MI->getOperand(OpNo).getReg(), MAI, OS);
966*0fca6ea1SDimitry Andric       return false;
967*0fca6ea1SDimitry Andric     }
968*0fca6ea1SDimitry Andric   }
969349cc55cSDimitry Andric   printAddress(MAI, MI->getOperand(OpNo).getReg(),
970349cc55cSDimitry Andric                MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()),
9710b57cec5SDimitry Andric                MI->getOperand(OpNo + 2).getReg(), OS);
9720b57cec5SDimitry Andric   return false;
9730b57cec5SDimitry Andric }
9740b57cec5SDimitry Andric 
9755ffd83dbSDimitry Andric void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) {
97606c3fb27SDimitry Andric   auto TT = OutContext.getTargetTriple();
97706c3fb27SDimitry Andric   if (TT.isOSzOS()) {
97806c3fb27SDimitry Andric     emitADASection();
9795f757f3fSDimitry Andric     emitIDRLSection(M);
98006c3fb27SDimitry Andric   }
981bdd1243dSDimitry Andric   emitAttributes(M);
9820b57cec5SDimitry Andric }
9830b57cec5SDimitry Andric 
98406c3fb27SDimitry Andric void SystemZAsmPrinter::emitADASection() {
98506c3fb27SDimitry Andric   OutStreamer->pushSection();
98606c3fb27SDimitry Andric 
98706c3fb27SDimitry Andric   const unsigned PointerSize = getDataLayout().getPointerSize();
98806c3fb27SDimitry Andric   OutStreamer->switchSection(getObjFileLowering().getADASection());
98906c3fb27SDimitry Andric 
99006c3fb27SDimitry Andric   unsigned EmittedBytes = 0;
99106c3fb27SDimitry Andric   for (auto &Entry : ADATable.getTable()) {
99206c3fb27SDimitry Andric     const MCSymbol *Sym;
99306c3fb27SDimitry Andric     unsigned SlotKind;
99406c3fb27SDimitry Andric     std::tie(Sym, SlotKind) = Entry.first;
99506c3fb27SDimitry Andric     unsigned Offset = Entry.second;
99606c3fb27SDimitry Andric     assert(Offset == EmittedBytes && "Offset not as expected");
99706c3fb27SDimitry Andric     (void)EmittedBytes;
99806c3fb27SDimitry Andric #define EMIT_COMMENT(Str)                                                      \
99906c3fb27SDimitry Andric   OutStreamer->AddComment(Twine("Offset ")                                     \
100006c3fb27SDimitry Andric                               .concat(utostr(Offset))                          \
100106c3fb27SDimitry Andric                               .concat(" " Str " ")                             \
100206c3fb27SDimitry Andric                               .concat(Sym->getName()));
100306c3fb27SDimitry Andric     switch (SlotKind) {
100406c3fb27SDimitry Andric     case SystemZII::MO_ADA_DIRECT_FUNC_DESC:
100506c3fb27SDimitry Andric       // Language Environment DLL logic requires function descriptors, for
100606c3fb27SDimitry Andric       // imported functions, that are placed in the ADA to be 8 byte aligned.
100706c3fb27SDimitry Andric       EMIT_COMMENT("function descriptor of");
100806c3fb27SDimitry Andric       OutStreamer->emitValue(
100906c3fb27SDimitry Andric           SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_RCon,
101006c3fb27SDimitry Andric                                 MCSymbolRefExpr::create(Sym, OutContext),
101106c3fb27SDimitry Andric                                 OutContext),
101206c3fb27SDimitry Andric           PointerSize);
101306c3fb27SDimitry Andric       OutStreamer->emitValue(
101406c3fb27SDimitry Andric           SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_VCon,
101506c3fb27SDimitry Andric                                 MCSymbolRefExpr::create(Sym, OutContext),
101606c3fb27SDimitry Andric                                 OutContext),
101706c3fb27SDimitry Andric           PointerSize);
101806c3fb27SDimitry Andric       EmittedBytes += PointerSize * 2;
101906c3fb27SDimitry Andric       break;
102006c3fb27SDimitry Andric     case SystemZII::MO_ADA_DATA_SYMBOL_ADDR:
102106c3fb27SDimitry Andric       EMIT_COMMENT("pointer to data symbol");
102206c3fb27SDimitry Andric       OutStreamer->emitValue(
102306c3fb27SDimitry Andric           SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_None,
102406c3fb27SDimitry Andric                                 MCSymbolRefExpr::create(Sym, OutContext),
102506c3fb27SDimitry Andric                                 OutContext),
102606c3fb27SDimitry Andric           PointerSize);
102706c3fb27SDimitry Andric       EmittedBytes += PointerSize;
102806c3fb27SDimitry Andric       break;
102906c3fb27SDimitry Andric     case SystemZII::MO_ADA_INDIRECT_FUNC_DESC: {
103006c3fb27SDimitry Andric       MCSymbol *Alias = OutContext.createTempSymbol(
103106c3fb27SDimitry Andric           Twine(Sym->getName()).concat("@indirect"));
103206c3fb27SDimitry Andric       OutStreamer->emitAssignment(Alias,
103306c3fb27SDimitry Andric                                   MCSymbolRefExpr::create(Sym, OutContext));
103406c3fb27SDimitry Andric       OutStreamer->emitSymbolAttribute(Alias, MCSA_IndirectSymbol);
103506c3fb27SDimitry Andric 
103606c3fb27SDimitry Andric       EMIT_COMMENT("pointer to function descriptor");
103706c3fb27SDimitry Andric       OutStreamer->emitValue(
103806c3fb27SDimitry Andric           SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_VCon,
103906c3fb27SDimitry Andric                                 MCSymbolRefExpr::create(Alias, OutContext),
104006c3fb27SDimitry Andric                                 OutContext),
104106c3fb27SDimitry Andric           PointerSize);
104206c3fb27SDimitry Andric       EmittedBytes += PointerSize;
104306c3fb27SDimitry Andric       break;
104406c3fb27SDimitry Andric     }
104506c3fb27SDimitry Andric     default:
104606c3fb27SDimitry Andric       llvm_unreachable("Unexpected slot kind");
104706c3fb27SDimitry Andric     }
104806c3fb27SDimitry Andric #undef EMIT_COMMENT
104906c3fb27SDimitry Andric   }
105006c3fb27SDimitry Andric   OutStreamer->popSection();
105106c3fb27SDimitry Andric }
105206c3fb27SDimitry Andric 
10535f757f3fSDimitry Andric static std::string getProductID(Module &M) {
10545f757f3fSDimitry Andric   std::string ProductID;
10555f757f3fSDimitry Andric   if (auto *MD = M.getModuleFlag("zos_product_id"))
10565f757f3fSDimitry Andric     ProductID = cast<MDString>(MD)->getString().str();
10575f757f3fSDimitry Andric   if (ProductID.empty())
10585f757f3fSDimitry Andric     ProductID = "LLVM";
10595f757f3fSDimitry Andric   return ProductID;
10605f757f3fSDimitry Andric }
10615f757f3fSDimitry Andric 
10625f757f3fSDimitry Andric static uint32_t getProductVersion(Module &M) {
10635f757f3fSDimitry Andric   if (auto *VersionVal = mdconst::extract_or_null<ConstantInt>(
10645f757f3fSDimitry Andric           M.getModuleFlag("zos_product_major_version")))
10655f757f3fSDimitry Andric     return VersionVal->getZExtValue();
10665f757f3fSDimitry Andric   return LLVM_VERSION_MAJOR;
10675f757f3fSDimitry Andric }
10685f757f3fSDimitry Andric 
10695f757f3fSDimitry Andric static uint32_t getProductRelease(Module &M) {
10705f757f3fSDimitry Andric   if (auto *ReleaseVal = mdconst::extract_or_null<ConstantInt>(
10715f757f3fSDimitry Andric           M.getModuleFlag("zos_product_minor_version")))
10725f757f3fSDimitry Andric     return ReleaseVal->getZExtValue();
10735f757f3fSDimitry Andric   return LLVM_VERSION_MINOR;
10745f757f3fSDimitry Andric }
10755f757f3fSDimitry Andric 
10765f757f3fSDimitry Andric static uint32_t getProductPatch(Module &M) {
10775f757f3fSDimitry Andric   if (auto *PatchVal = mdconst::extract_or_null<ConstantInt>(
10785f757f3fSDimitry Andric           M.getModuleFlag("zos_product_patchlevel")))
10795f757f3fSDimitry Andric     return PatchVal->getZExtValue();
10805f757f3fSDimitry Andric   return LLVM_VERSION_PATCH;
10815f757f3fSDimitry Andric }
10825f757f3fSDimitry Andric 
10835f757f3fSDimitry Andric static time_t getTranslationTime(Module &M) {
10845f757f3fSDimitry Andric   std::time_t Time = 0;
10855f757f3fSDimitry Andric   if (auto *Val = mdconst::extract_or_null<ConstantInt>(
10865f757f3fSDimitry Andric           M.getModuleFlag("zos_translation_time"))) {
10875f757f3fSDimitry Andric     long SecondsSinceEpoch = Val->getSExtValue();
10885f757f3fSDimitry Andric     Time = static_cast<time_t>(SecondsSinceEpoch);
10895f757f3fSDimitry Andric   }
10905f757f3fSDimitry Andric   return Time;
10915f757f3fSDimitry Andric }
10925f757f3fSDimitry Andric 
10935f757f3fSDimitry Andric void SystemZAsmPrinter::emitIDRLSection(Module &M) {
10945f757f3fSDimitry Andric   OutStreamer->pushSection();
10955f757f3fSDimitry Andric   OutStreamer->switchSection(getObjFileLowering().getIDRLSection());
10965f757f3fSDimitry Andric   constexpr unsigned IDRLDataLength = 30;
10975f757f3fSDimitry Andric   std::time_t Time = getTranslationTime(M);
10985f757f3fSDimitry Andric 
10995f757f3fSDimitry Andric   uint32_t ProductVersion = getProductVersion(M);
11005f757f3fSDimitry Andric   uint32_t ProductRelease = getProductRelease(M);
11015f757f3fSDimitry Andric 
11025f757f3fSDimitry Andric   std::string ProductID = getProductID(M);
11035f757f3fSDimitry Andric 
11045f757f3fSDimitry Andric   SmallString<IDRLDataLength + 1> TempStr;
11055f757f3fSDimitry Andric   raw_svector_ostream O(TempStr);
11065f757f3fSDimitry Andric   O << formatv("{0,-10}{1,0-2:d}{2,0-2:d}{3:%Y%m%d%H%M%S}{4,0-2}",
11075f757f3fSDimitry Andric                ProductID.substr(0, 10).c_str(), ProductVersion, ProductRelease,
11085f757f3fSDimitry Andric                llvm::sys::toUtcTime(Time), "0");
11095f757f3fSDimitry Andric   SmallString<IDRLDataLength> Data;
11105f757f3fSDimitry Andric   ConverterEBCDIC::convertToEBCDIC(TempStr, Data);
11115f757f3fSDimitry Andric 
11125f757f3fSDimitry Andric   OutStreamer->emitInt8(0);               // Reserved.
11135f757f3fSDimitry Andric   OutStreamer->emitInt8(3);               // Format.
11145f757f3fSDimitry Andric   OutStreamer->emitInt16(IDRLDataLength); // Length.
11155f757f3fSDimitry Andric   OutStreamer->emitBytes(Data.str());
11165f757f3fSDimitry Andric   OutStreamer->popSection();
11175f757f3fSDimitry Andric }
11185f757f3fSDimitry Andric 
111981ad6265SDimitry Andric void SystemZAsmPrinter::emitFunctionBodyEnd() {
112081ad6265SDimitry Andric   if (TM.getTargetTriple().isOSzOS()) {
112181ad6265SDimitry Andric     // Emit symbol for the end of function if the z/OS target streamer
112281ad6265SDimitry Andric     // is used. This is needed to calculate the size of the function.
112381ad6265SDimitry Andric     MCSymbol *FnEndSym = createTempSymbol("func_end");
112481ad6265SDimitry Andric     OutStreamer->emitLabel(FnEndSym);
112581ad6265SDimitry Andric 
112681ad6265SDimitry Andric     OutStreamer->pushSection();
112781ad6265SDimitry Andric     OutStreamer->switchSection(getObjFileLowering().getPPA1Section());
112881ad6265SDimitry Andric     emitPPA1(FnEndSym);
112981ad6265SDimitry Andric     OutStreamer->popSection();
113081ad6265SDimitry Andric 
113181ad6265SDimitry Andric     CurrentFnPPA1Sym = nullptr;
113281ad6265SDimitry Andric     CurrentFnEPMarkerSym = nullptr;
113381ad6265SDimitry Andric   }
113481ad6265SDimitry Andric }
113581ad6265SDimitry Andric 
113681ad6265SDimitry Andric static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg,
11375f757f3fSDimitry Andric                           bool StackProtector, bool FPRMask, bool VRMask,
1138cb14a3feSDimitry Andric                           bool EHBlock, bool HasName) {
113981ad6265SDimitry Andric   enum class PPA1Flag1 : uint8_t {
114081ad6265SDimitry Andric     DSA64Bit = (0x80 >> 0),
114181ad6265SDimitry Andric     VarArg = (0x80 >> 7),
114281ad6265SDimitry Andric     LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit)
114381ad6265SDimitry Andric   };
114481ad6265SDimitry Andric   enum class PPA1Flag2 : uint8_t {
114581ad6265SDimitry Andric     ExternalProcedure = (0x80 >> 0),
114681ad6265SDimitry Andric     STACKPROTECTOR = (0x80 >> 3),
114781ad6265SDimitry Andric     LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure)
114881ad6265SDimitry Andric   };
114981ad6265SDimitry Andric   enum class PPA1Flag3 : uint8_t {
115081ad6265SDimitry Andric     FPRMask = (0x80 >> 2),
115181ad6265SDimitry Andric     LLVM_MARK_AS_BITMASK_ENUM(FPRMask)
115281ad6265SDimitry Andric   };
115381ad6265SDimitry Andric   enum class PPA1Flag4 : uint8_t {
115481ad6265SDimitry Andric     EPMOffsetPresent = (0x80 >> 0),
115581ad6265SDimitry Andric     VRMask = (0x80 >> 2),
1156cb14a3feSDimitry Andric     EHBlock = (0x80 >> 3),
115781ad6265SDimitry Andric     ProcedureNamePresent = (0x80 >> 7),
115881ad6265SDimitry Andric     LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent)
115981ad6265SDimitry Andric   };
116081ad6265SDimitry Andric 
116181ad6265SDimitry Andric   // Declare optional section flags that can be modified.
116281ad6265SDimitry Andric   auto Flags1 = PPA1Flag1(0);
116381ad6265SDimitry Andric   auto Flags2 = PPA1Flag2::ExternalProcedure;
116481ad6265SDimitry Andric   auto Flags3 = PPA1Flag3(0);
11655f757f3fSDimitry Andric   auto Flags4 = PPA1Flag4::EPMOffsetPresent;
116681ad6265SDimitry Andric 
116781ad6265SDimitry Andric   Flags1 |= PPA1Flag1::DSA64Bit;
116881ad6265SDimitry Andric 
116981ad6265SDimitry Andric   if (VarArg)
117081ad6265SDimitry Andric     Flags1 |= PPA1Flag1::VarArg;
117181ad6265SDimitry Andric 
117281ad6265SDimitry Andric   if (StackProtector)
117381ad6265SDimitry Andric     Flags2 |= PPA1Flag2::STACKPROTECTOR;
117481ad6265SDimitry Andric 
117581ad6265SDimitry Andric   // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in.
117681ad6265SDimitry Andric   if (FPRMask)
117781ad6265SDimitry Andric     Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag.
117881ad6265SDimitry Andric 
117981ad6265SDimitry Andric   if (VRMask)
118081ad6265SDimitry Andric     Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag.
118181ad6265SDimitry Andric 
1182cb14a3feSDimitry Andric   if (EHBlock)
1183cb14a3feSDimitry Andric     Flags4 |= PPA1Flag4::EHBlock; // Add optional EH block.
1184cb14a3feSDimitry Andric 
11855f757f3fSDimitry Andric   if (HasName)
11865f757f3fSDimitry Andric     Flags4 |= PPA1Flag4::ProcedureNamePresent; // Add optional name block.
11875f757f3fSDimitry Andric 
118881ad6265SDimitry Andric   OutStreamer->AddComment("PPA1 Flags 1");
118981ad6265SDimitry Andric   if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit)
119081ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 0: 1 = 64-bit DSA");
119181ad6265SDimitry Andric   else
119281ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 0: 0 = 32-bit DSA");
119381ad6265SDimitry Andric   if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg)
119481ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 7: 1 = Vararg function");
119581ad6265SDimitry Andric   OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1.
119681ad6265SDimitry Andric 
119781ad6265SDimitry Andric   OutStreamer->AddComment("PPA1 Flags 2");
119881ad6265SDimitry Andric   if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure)
119981ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 0: 1 = External procedure");
120081ad6265SDimitry Andric   if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR)
120181ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 3: 1 = STACKPROTECT is enabled");
120281ad6265SDimitry Andric   else
120381ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 3: 0 = STACKPROTECT is not enabled");
120481ad6265SDimitry Andric   OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2.
120581ad6265SDimitry Andric 
120681ad6265SDimitry Andric   OutStreamer->AddComment("PPA1 Flags 3");
120781ad6265SDimitry Andric   if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask)
120881ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 2: 1 = FP Reg Mask is in optional area");
120981ad6265SDimitry Andric   OutStreamer->emitInt8(
121081ad6265SDimitry Andric       static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections).
121181ad6265SDimitry Andric 
121281ad6265SDimitry Andric   OutStreamer->AddComment("PPA1 Flags 4");
121381ad6265SDimitry Andric   if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask)
121481ad6265SDimitry Andric     OutStreamer->AddComment("  Bit 2: 1 = Vector Reg Mask is in optional area");
1215cb14a3feSDimitry Andric   if ((Flags4 & PPA1Flag4::EHBlock) == PPA1Flag4::EHBlock)
1216cb14a3feSDimitry Andric     OutStreamer->AddComment("  Bit 3: 1 = C++ EH block");
12175f757f3fSDimitry Andric   if ((Flags4 & PPA1Flag4::ProcedureNamePresent) ==
12185f757f3fSDimitry Andric       PPA1Flag4::ProcedureNamePresent)
12195f757f3fSDimitry Andric     OutStreamer->AddComment("  Bit 7: 1 = Name Length and Name");
122081ad6265SDimitry Andric   OutStreamer->emitInt8(static_cast<uint8_t>(
122181ad6265SDimitry Andric       Flags4)); // Flags 4 (optional sections, always emit these).
122281ad6265SDimitry Andric }
122381ad6265SDimitry Andric 
12245f757f3fSDimitry Andric static void emitPPA1Name(std::unique_ptr<MCStreamer> &OutStreamer,
12255f757f3fSDimitry Andric                          StringRef OutName) {
12265f757f3fSDimitry Andric   size_t NameSize = OutName.size();
12275f757f3fSDimitry Andric   uint16_t OutSize;
12285f757f3fSDimitry Andric   if (NameSize < UINT16_MAX) {
12295f757f3fSDimitry Andric     OutSize = static_cast<uint16_t>(NameSize);
12305f757f3fSDimitry Andric   } else {
12315f757f3fSDimitry Andric     OutName = OutName.substr(0, UINT16_MAX);
12325f757f3fSDimitry Andric     OutSize = UINT16_MAX;
12335f757f3fSDimitry Andric   }
12345f757f3fSDimitry Andric   // Emit padding to ensure that the next optional field word-aligned.
12355f757f3fSDimitry Andric   uint8_t ExtraZeros = 4 - ((2 + OutSize) % 4);
12365f757f3fSDimitry Andric 
12375f757f3fSDimitry Andric   SmallString<512> OutnameConv;
12385f757f3fSDimitry Andric   ConverterEBCDIC::convertToEBCDIC(OutName, OutnameConv);
12395f757f3fSDimitry Andric   OutName = OutnameConv.str();
12405f757f3fSDimitry Andric 
12415f757f3fSDimitry Andric   OutStreamer->AddComment("Length of Name");
12425f757f3fSDimitry Andric   OutStreamer->emitInt16(OutSize);
12435f757f3fSDimitry Andric   OutStreamer->AddComment("Name of Function");
12445f757f3fSDimitry Andric   OutStreamer->emitBytes(OutName);
12455f757f3fSDimitry Andric   OutStreamer->emitZeros(ExtraZeros);
12465f757f3fSDimitry Andric }
12475f757f3fSDimitry Andric 
124881ad6265SDimitry Andric void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) {
12495f757f3fSDimitry Andric   assert(PPA2Sym != nullptr && "PPA2 Symbol not defined");
12505f757f3fSDimitry Andric 
125181ad6265SDimitry Andric   const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo();
125281ad6265SDimitry Andric   const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
125381ad6265SDimitry Andric   const auto TargetHasVector = Subtarget.hasVector();
125481ad6265SDimitry Andric 
125581ad6265SDimitry Andric   const SystemZMachineFunctionInfo *ZFI =
125681ad6265SDimitry Andric       MF->getInfo<SystemZMachineFunctionInfo>();
125781ad6265SDimitry Andric   const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>(
125881ad6265SDimitry Andric       Subtarget.getFrameLowering());
125981ad6265SDimitry Andric   const MachineFrameInfo &MFFrame = MF->getFrameInfo();
126081ad6265SDimitry Andric 
126181ad6265SDimitry Andric   // Get saved GPR/FPR/VPR masks.
126281ad6265SDimitry Andric   const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo();
126381ad6265SDimitry Andric   uint16_t SavedGPRMask = 0;
126481ad6265SDimitry Andric   uint16_t SavedFPRMask = 0;
126581ad6265SDimitry Andric   uint8_t SavedVRMask = 0;
126681ad6265SDimitry Andric   int64_t OffsetFPR = 0;
126781ad6265SDimitry Andric   int64_t OffsetVR = 0;
126881ad6265SDimitry Andric   const int64_t TopOfStack =
126981ad6265SDimitry Andric       MFFrame.getOffsetAdjustment() + MFFrame.getStackSize();
127081ad6265SDimitry Andric 
127181ad6265SDimitry Andric   // Loop over the spilled registers. The CalleeSavedInfo can't be used because
127281ad6265SDimitry Andric   // it does not contain all spilled registers.
127381ad6265SDimitry Andric   for (unsigned I = ZFI->getSpillGPRRegs().LowGPR,
127481ad6265SDimitry Andric                 E = ZFI->getSpillGPRRegs().HighGPR;
127581ad6265SDimitry Andric        I && E && I <= E; ++I) {
127681ad6265SDimitry Andric     unsigned V = TRI->getEncodingValue((Register)I);
127781ad6265SDimitry Andric     assert(V < 16 && "GPR index out of range");
127881ad6265SDimitry Andric     SavedGPRMask |= 1 << (15 - V);
127981ad6265SDimitry Andric   }
128081ad6265SDimitry Andric 
128181ad6265SDimitry Andric   for (auto &CS : CSI) {
128281ad6265SDimitry Andric     unsigned Reg = CS.getReg();
128381ad6265SDimitry Andric     unsigned I = TRI->getEncodingValue(Reg);
128481ad6265SDimitry Andric 
128581ad6265SDimitry Andric     if (SystemZ::FP64BitRegClass.contains(Reg)) {
128681ad6265SDimitry Andric       assert(I < 16 && "FPR index out of range");
128781ad6265SDimitry Andric       SavedFPRMask |= 1 << (15 - I);
128881ad6265SDimitry Andric       int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
128981ad6265SDimitry Andric       if (Temp < OffsetFPR)
129081ad6265SDimitry Andric         OffsetFPR = Temp;
129181ad6265SDimitry Andric     } else if (SystemZ::VR128BitRegClass.contains(Reg)) {
129281ad6265SDimitry Andric       assert(I >= 16 && I <= 23 && "VPR index out of range");
129381ad6265SDimitry Andric       unsigned BitNum = I - 16;
129481ad6265SDimitry Andric       SavedVRMask |= 1 << (7 - BitNum);
129581ad6265SDimitry Andric       int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx());
129681ad6265SDimitry Andric       if (Temp < OffsetVR)
129781ad6265SDimitry Andric         OffsetVR = Temp;
129881ad6265SDimitry Andric     }
129981ad6265SDimitry Andric   }
130081ad6265SDimitry Andric 
130181ad6265SDimitry Andric   // Adjust the offset.
130281ad6265SDimitry Andric   OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0;
130381ad6265SDimitry Andric   OffsetVR += (OffsetVR < 0) ? TopOfStack : 0;
130481ad6265SDimitry Andric 
130581ad6265SDimitry Andric   // Get alloca register.
130681ad6265SDimitry Andric   uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF));
130781ad6265SDimitry Andric   uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0;
130881ad6265SDimitry Andric   assert(AllocaReg < 16 && "Can't have alloca register larger than 15");
130981ad6265SDimitry Andric   (void)AllocaReg;
131081ad6265SDimitry Andric 
131181ad6265SDimitry Andric   // Build FPR save area offset.
131281ad6265SDimitry Andric   uint32_t FrameAndFPROffset = 0;
131381ad6265SDimitry Andric   if (SavedFPRMask) {
131481ad6265SDimitry Andric     uint64_t FPRSaveAreaOffset = OffsetFPR;
131581ad6265SDimitry Andric     assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range");
131681ad6265SDimitry Andric 
131781ad6265SDimitry Andric     FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
131881ad6265SDimitry Andric     FrameAndFPROffset |= FrameReg << 28;                // Put into top 4 bits.
131981ad6265SDimitry Andric   }
132081ad6265SDimitry Andric 
132181ad6265SDimitry Andric   // Build VR save area offset.
132281ad6265SDimitry Andric   uint32_t FrameAndVROffset = 0;
132381ad6265SDimitry Andric   if (TargetHasVector && SavedVRMask) {
132481ad6265SDimitry Andric     uint64_t VRSaveAreaOffset = OffsetVR;
132581ad6265SDimitry Andric     assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range");
132681ad6265SDimitry Andric 
132781ad6265SDimitry Andric     FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits.
132881ad6265SDimitry Andric     FrameAndVROffset |= FrameReg << 28;               // Put into top 4 bits.
132981ad6265SDimitry Andric   }
133081ad6265SDimitry Andric 
133181ad6265SDimitry Andric   // Emit PPA1 section.
133281ad6265SDimitry Andric   OutStreamer->AddComment("PPA1");
133381ad6265SDimitry Andric   OutStreamer->emitLabel(CurrentFnPPA1Sym);
133481ad6265SDimitry Andric   OutStreamer->AddComment("Version");
133581ad6265SDimitry Andric   OutStreamer->emitInt8(0x02); // Version.
133681ad6265SDimitry Andric   OutStreamer->AddComment("LE Signature X'CE'");
133781ad6265SDimitry Andric   OutStreamer->emitInt8(0xCE); // CEL signature.
133881ad6265SDimitry Andric   OutStreamer->AddComment("Saved GPR Mask");
133981ad6265SDimitry Andric   OutStreamer->emitInt16(SavedGPRMask);
13405f757f3fSDimitry Andric   OutStreamer->AddComment("Offset to PPA2");
13415f757f3fSDimitry Andric   OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CurrentFnPPA1Sym, 4);
13425f757f3fSDimitry Andric 
1343cb14a3feSDimitry Andric   bool NeedEmitEHBlock = !MF->getLandingPads().empty();
1344cb14a3feSDimitry Andric 
13455f757f3fSDimitry Andric   bool HasName =
13465f757f3fSDimitry Andric       MF->getFunction().hasName() && MF->getFunction().getName().size() > 0;
134781ad6265SDimitry Andric 
134881ad6265SDimitry Andric   emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(),
134981ad6265SDimitry Andric                 MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0,
1350cb14a3feSDimitry Andric                 TargetHasVector && SavedVRMask != 0, NeedEmitEHBlock, HasName);
135181ad6265SDimitry Andric 
135281ad6265SDimitry Andric   OutStreamer->AddComment("Length/4 of Parms");
135381ad6265SDimitry Andric   OutStreamer->emitInt16(
135406c3fb27SDimitry Andric       static_cast<uint16_t>(ZFI->getSizeOfFnParams() / 4)); // Parms/4.
135581ad6265SDimitry Andric   OutStreamer->AddComment("Length of Code");
135681ad6265SDimitry Andric   OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4);
135781ad6265SDimitry Andric 
135881ad6265SDimitry Andric   // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3).
135981ad6265SDimitry Andric   if (SavedFPRMask) {
136081ad6265SDimitry Andric     OutStreamer->AddComment("FPR mask");
136181ad6265SDimitry Andric     OutStreamer->emitInt16(SavedFPRMask);
136281ad6265SDimitry Andric     OutStreamer->AddComment("AR mask");
136381ad6265SDimitry Andric     OutStreamer->emitInt16(0); // AR Mask, unused currently.
136481ad6265SDimitry Andric     OutStreamer->AddComment("FPR Save Area Locator");
136581ad6265SDimitry Andric     OutStreamer->AddComment(Twine("  Bit 0-3: Register R")
136681ad6265SDimitry Andric                                 .concat(utostr(FrameAndFPROffset >> 28))
136781ad6265SDimitry Andric                                 .str());
136881ad6265SDimitry Andric     OutStreamer->AddComment(Twine("  Bit 4-31: Offset ")
136981ad6265SDimitry Andric                                 .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF))
137081ad6265SDimitry Andric                                 .str());
137181ad6265SDimitry Andric     OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with
137281ad6265SDimitry Andric                                                // register to add value to
137381ad6265SDimitry Andric                                                // (alloca reg).
137481ad6265SDimitry Andric   }
137581ad6265SDimitry Andric 
137681ad6265SDimitry Andric   // Emit saved VR mask to VR save area.
137781ad6265SDimitry Andric   if (TargetHasVector && SavedVRMask) {
137881ad6265SDimitry Andric     OutStreamer->AddComment("VR mask");
137981ad6265SDimitry Andric     OutStreamer->emitInt8(SavedVRMask);
138081ad6265SDimitry Andric     OutStreamer->emitInt8(0);  // Reserved.
138181ad6265SDimitry Andric     OutStreamer->emitInt16(0); // Also reserved.
138281ad6265SDimitry Andric     OutStreamer->AddComment("VR Save Area Locator");
138381ad6265SDimitry Andric     OutStreamer->AddComment(Twine("  Bit 0-3: Register R")
138481ad6265SDimitry Andric                                 .concat(utostr(FrameAndVROffset >> 28))
138581ad6265SDimitry Andric                                 .str());
138681ad6265SDimitry Andric     OutStreamer->AddComment(Twine("  Bit 4-31: Offset ")
138781ad6265SDimitry Andric                                 .concat(utostr(FrameAndVROffset & 0x0FFFFFFF))
138881ad6265SDimitry Andric                                 .str());
138981ad6265SDimitry Andric     OutStreamer->emitInt32(FrameAndVROffset);
139081ad6265SDimitry Andric   }
139181ad6265SDimitry Andric 
1392cb14a3feSDimitry Andric   // Emit C++ EH information block
1393cb14a3feSDimitry Andric   const Function *Per = nullptr;
1394cb14a3feSDimitry Andric   if (NeedEmitEHBlock) {
1395cb14a3feSDimitry Andric     Per = dyn_cast<Function>(
1396cb14a3feSDimitry Andric         MF->getFunction().getPersonalityFn()->stripPointerCasts());
1397cb14a3feSDimitry Andric     MCSymbol *PersonalityRoutine =
1398cb14a3feSDimitry Andric         Per ? MF->getTarget().getSymbol(Per) : nullptr;
1399cb14a3feSDimitry Andric     assert(PersonalityRoutine && "Missing personality routine");
1400cb14a3feSDimitry Andric 
1401cb14a3feSDimitry Andric     OutStreamer->AddComment("Version");
1402cb14a3feSDimitry Andric     OutStreamer->emitInt32(1);
1403cb14a3feSDimitry Andric     OutStreamer->AddComment("Flags");
1404cb14a3feSDimitry Andric     OutStreamer->emitInt32(0); // LSDA field is a WAS offset
1405cb14a3feSDimitry Andric     OutStreamer->AddComment("Personality routine");
1406cb14a3feSDimitry Andric     OutStreamer->emitInt64(ADATable.insert(
1407cb14a3feSDimitry Andric         PersonalityRoutine, SystemZII::MO_ADA_INDIRECT_FUNC_DESC));
1408cb14a3feSDimitry Andric     OutStreamer->AddComment("LSDA location");
1409cb14a3feSDimitry Andric     MCSymbol *GCCEH = MF->getContext().getOrCreateSymbol(
1410cb14a3feSDimitry Andric         Twine("GCC_except_table") + Twine(MF->getFunctionNumber()));
1411cb14a3feSDimitry Andric     OutStreamer->emitInt64(
1412cb14a3feSDimitry Andric         ADATable.insert(GCCEH, SystemZII::MO_ADA_DATA_SYMBOL_ADDR));
1413cb14a3feSDimitry Andric   }
1414cb14a3feSDimitry Andric 
14155f757f3fSDimitry Andric   // Emit name length and name optional section (0x01 of flags 4)
14165f757f3fSDimitry Andric   if (HasName)
14175f757f3fSDimitry Andric     emitPPA1Name(OutStreamer, MF->getFunction().getName());
14185f757f3fSDimitry Andric 
141981ad6265SDimitry Andric   // Emit offset to entry point optional section (0x80 of flags 4).
142081ad6265SDimitry Andric   OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym,
142181ad6265SDimitry Andric                                       4);
142281ad6265SDimitry Andric }
142381ad6265SDimitry Andric 
14245f757f3fSDimitry Andric void SystemZAsmPrinter::emitStartOfAsmFile(Module &M) {
14255f757f3fSDimitry Andric   if (TM.getTargetTriple().isOSzOS())
14265f757f3fSDimitry Andric     emitPPA2(M);
14275f757f3fSDimitry Andric   AsmPrinter::emitStartOfAsmFile(M);
14285f757f3fSDimitry Andric }
14295f757f3fSDimitry Andric 
14305f757f3fSDimitry Andric void SystemZAsmPrinter::emitPPA2(Module &M) {
14315f757f3fSDimitry Andric   OutStreamer->pushSection();
14325f757f3fSDimitry Andric   OutStreamer->switchSection(getObjFileLowering().getPPA2Section());
14335f757f3fSDimitry Andric   MCContext &OutContext = OutStreamer->getContext();
14345f757f3fSDimitry Andric   // Make CELQSTRT symbol.
14355f757f3fSDimitry Andric   const char *StartSymbolName = "CELQSTRT";
14365f757f3fSDimitry Andric   MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName);
14375f757f3fSDimitry Andric 
14385f757f3fSDimitry Andric   // Create symbol and assign to class field for use in PPA1.
14395f757f3fSDimitry Andric   PPA2Sym = OutContext.createTempSymbol("PPA2", false);
14405f757f3fSDimitry Andric   MCSymbol *DateVersionSym = OutContext.createTempSymbol("DVS", false);
14415f757f3fSDimitry Andric 
14425f757f3fSDimitry Andric   std::time_t Time = getTranslationTime(M);
14435f757f3fSDimitry Andric   SmallString<15> CompilationTime; // 14 + null
14445f757f3fSDimitry Andric   raw_svector_ostream O(CompilationTime);
14455f757f3fSDimitry Andric   O << formatv("{0:%Y%m%d%H%M%S}", llvm::sys::toUtcTime(Time));
14465f757f3fSDimitry Andric 
14475f757f3fSDimitry Andric   uint32_t ProductVersion = getProductVersion(M),
14485f757f3fSDimitry Andric            ProductRelease = getProductRelease(M),
14495f757f3fSDimitry Andric            ProductPatch = getProductPatch(M);
14505f757f3fSDimitry Andric 
14515f757f3fSDimitry Andric   SmallString<7> Version; // 6 + null
14525f757f3fSDimitry Andric   raw_svector_ostream ostr(Version);
14535f757f3fSDimitry Andric   ostr << formatv("{0,0-2:d}{1,0-2:d}{2,0-2:d}", ProductVersion, ProductRelease,
14545f757f3fSDimitry Andric                   ProductPatch);
14555f757f3fSDimitry Andric 
14565f757f3fSDimitry Andric   // Drop 0 during conversion.
14575f757f3fSDimitry Andric   SmallString<sizeof(CompilationTime) - 1> CompilationTimeStr;
14585f757f3fSDimitry Andric   SmallString<sizeof(Version) - 1> VersionStr;
14595f757f3fSDimitry Andric 
14605f757f3fSDimitry Andric   ConverterEBCDIC::convertToEBCDIC(CompilationTime, CompilationTimeStr);
14615f757f3fSDimitry Andric   ConverterEBCDIC::convertToEBCDIC(Version, VersionStr);
14625f757f3fSDimitry Andric 
14635f757f3fSDimitry Andric   enum class PPA2MemberId : uint8_t {
14645f757f3fSDimitry Andric     // See z/OS Language Environment Vendor Interfaces v2r5, p.23, for
14655f757f3fSDimitry Andric     // complete list. Only the C runtime is supported by this backend.
14665f757f3fSDimitry Andric     LE_C_Runtime = 3,
14675f757f3fSDimitry Andric   };
14685f757f3fSDimitry Andric   enum class PPA2MemberSubId : uint8_t {
14695f757f3fSDimitry Andric     // List of languages using the LE C runtime implementation.
14705f757f3fSDimitry Andric     C = 0x00,
14715f757f3fSDimitry Andric     CXX = 0x01,
14725f757f3fSDimitry Andric     Swift = 0x03,
14735f757f3fSDimitry Andric     Go = 0x60,
14745f757f3fSDimitry Andric     LLVMBasedLang = 0xe7,
14755f757f3fSDimitry Andric   };
14765f757f3fSDimitry Andric   // PPA2 Flags
14775f757f3fSDimitry Andric   enum class PPA2Flags : uint8_t {
14785f757f3fSDimitry Andric     CompileForBinaryFloatingPoint = 0x80,
14795f757f3fSDimitry Andric     CompiledWithXPLink = 0x01,
14805f757f3fSDimitry Andric     CompiledUnitASCII = 0x04,
14815f757f3fSDimitry Andric     HasServiceInfo = 0x20,
14825f757f3fSDimitry Andric   };
14835f757f3fSDimitry Andric 
14845f757f3fSDimitry Andric   PPA2MemberSubId MemberSubId = PPA2MemberSubId::LLVMBasedLang;
14855f757f3fSDimitry Andric   if (auto *MD = M.getModuleFlag("zos_cu_language")) {
14865f757f3fSDimitry Andric     StringRef Language = cast<MDString>(MD)->getString();
14875f757f3fSDimitry Andric     MemberSubId = StringSwitch<PPA2MemberSubId>(Language)
14885f757f3fSDimitry Andric                       .Case("C", PPA2MemberSubId::C)
14895f757f3fSDimitry Andric                       .Case("C++", PPA2MemberSubId::CXX)
14905f757f3fSDimitry Andric                       .Case("Swift", PPA2MemberSubId::Swift)
14915f757f3fSDimitry Andric                       .Case("Go", PPA2MemberSubId::Go)
14925f757f3fSDimitry Andric                       .Default(PPA2MemberSubId::LLVMBasedLang);
14935f757f3fSDimitry Andric   }
14945f757f3fSDimitry Andric 
14955f757f3fSDimitry Andric   // Emit PPA2 section.
14965f757f3fSDimitry Andric   OutStreamer->emitLabel(PPA2Sym);
14975f757f3fSDimitry Andric   OutStreamer->emitInt8(static_cast<uint8_t>(PPA2MemberId::LE_C_Runtime));
14985f757f3fSDimitry Andric   OutStreamer->emitInt8(static_cast<uint8_t>(MemberSubId));
14995f757f3fSDimitry Andric   OutStreamer->emitInt8(0x22); // Member defined, c370_plist+c370_env
15005f757f3fSDimitry Andric   OutStreamer->emitInt8(0x04); // Control level 4 (XPLink)
15015f757f3fSDimitry Andric   OutStreamer->emitAbsoluteSymbolDiff(CELQSTRT, PPA2Sym, 4);
15025f757f3fSDimitry Andric   OutStreamer->emitInt32(0x00000000);
15035f757f3fSDimitry Andric   OutStreamer->emitAbsoluteSymbolDiff(DateVersionSym, PPA2Sym, 4);
15045f757f3fSDimitry Andric   OutStreamer->emitInt32(
15055f757f3fSDimitry Andric       0x00000000); // Offset to main entry point, always 0 (so says TR).
15065f757f3fSDimitry Andric   uint8_t Flgs = static_cast<uint8_t>(PPA2Flags::CompileForBinaryFloatingPoint);
15075f757f3fSDimitry Andric   Flgs |= static_cast<uint8_t>(PPA2Flags::CompiledWithXPLink);
15085f757f3fSDimitry Andric 
15095f757f3fSDimitry Andric   if (auto *MD = M.getModuleFlag("zos_le_char_mode")) {
15105f757f3fSDimitry Andric     const StringRef &CharMode = cast<MDString>(MD)->getString();
15115f757f3fSDimitry Andric     if (CharMode == "ascii") {
15125f757f3fSDimitry Andric       Flgs |= static_cast<uint8_t>(
15135f757f3fSDimitry Andric           PPA2Flags::CompiledUnitASCII); // Setting bit for ASCII char. mode.
15145f757f3fSDimitry Andric     } else if (CharMode != "ebcdic") {
15155f757f3fSDimitry Andric       report_fatal_error(
15165f757f3fSDimitry Andric           "Only ascii or ebcdic are valid values for zos_le_char_mode "
15175f757f3fSDimitry Andric           "metadata");
15185f757f3fSDimitry Andric     }
15195f757f3fSDimitry Andric   }
15205f757f3fSDimitry Andric 
15215f757f3fSDimitry Andric   OutStreamer->emitInt8(Flgs);
15225f757f3fSDimitry Andric   OutStreamer->emitInt8(0x00);    // Reserved.
15235f757f3fSDimitry Andric                                   // No MD5 signature before timestamp.
15245f757f3fSDimitry Andric                                   // No FLOAT(AFP(VOLATILE)).
15255f757f3fSDimitry Andric                                   // Remaining 5 flag bits reserved.
15265f757f3fSDimitry Andric   OutStreamer->emitInt16(0x0000); // 16 Reserved flag bits.
15275f757f3fSDimitry Andric 
15285f757f3fSDimitry Andric   // Emit date and version section.
15295f757f3fSDimitry Andric   OutStreamer->emitLabel(DateVersionSym);
15305f757f3fSDimitry Andric   OutStreamer->emitBytes(CompilationTimeStr.str());
15315f757f3fSDimitry Andric   OutStreamer->emitBytes(VersionStr.str());
15325f757f3fSDimitry Andric 
15335f757f3fSDimitry Andric   OutStreamer->emitInt16(0x0000); // Service level string length.
15345f757f3fSDimitry Andric 
1535*0fca6ea1SDimitry Andric   // The binder requires that the offset to the PPA2 be emitted in a different,
1536*0fca6ea1SDimitry Andric   // specially-named section.
1537*0fca6ea1SDimitry Andric   OutStreamer->switchSection(getObjFileLowering().getPPA2ListSection());
15385f757f3fSDimitry Andric   // Emit 8 byte alignment.
15395f757f3fSDimitry Andric   // Emit pointer to PPA2 label.
15405f757f3fSDimitry Andric   OutStreamer->AddComment("A(PPA2-CELQSTRT)");
15415f757f3fSDimitry Andric   OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CELQSTRT, 8);
15425f757f3fSDimitry Andric   OutStreamer->popSection();
15435f757f3fSDimitry Andric }
15445f757f3fSDimitry Andric 
154504eeddc0SDimitry Andric void SystemZAsmPrinter::emitFunctionEntryLabel() {
154681ad6265SDimitry Andric   const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>();
154704eeddc0SDimitry Andric 
154804eeddc0SDimitry Andric   if (Subtarget.getTargetTriple().isOSzOS()) {
154904eeddc0SDimitry Andric     MCContext &OutContext = OutStreamer->getContext();
155081ad6265SDimitry Andric 
155181ad6265SDimitry Andric     // Save information for later use.
155281ad6265SDimitry Andric     std::string N(MF->getFunction().hasName()
155381ad6265SDimitry Andric                       ? Twine(MF->getFunction().getName()).concat("_").str()
155481ad6265SDimitry Andric                       : "");
155581ad6265SDimitry Andric 
155681ad6265SDimitry Andric     CurrentFnEPMarkerSym =
155781ad6265SDimitry Andric         OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true);
155881ad6265SDimitry Andric     CurrentFnPPA1Sym =
155981ad6265SDimitry Andric         OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true);
156004eeddc0SDimitry Andric 
156104eeddc0SDimitry Andric     // EntryPoint Marker
156204eeddc0SDimitry Andric     const MachineFrameInfo &MFFrame = MF->getFrameInfo();
156304eeddc0SDimitry Andric     bool IsUsingAlloca = MFFrame.hasVarSizedObjects();
15645f757f3fSDimitry Andric     uint32_t DSASize = MFFrame.getStackSize();
15655f757f3fSDimitry Andric     bool IsLeaf = DSASize == 0 && MFFrame.getCalleeSavedInfo().empty();
156604eeddc0SDimitry Andric 
15675f757f3fSDimitry Andric     // Set Flags.
156804eeddc0SDimitry Andric     uint8_t Flags = 0;
15695f757f3fSDimitry Andric     if (IsLeaf)
15705f757f3fSDimitry Andric       Flags |= 0x08;
157104eeddc0SDimitry Andric     if (IsUsingAlloca)
157204eeddc0SDimitry Andric       Flags |= 0x04;
157304eeddc0SDimitry Andric 
157404eeddc0SDimitry Andric     // Combine into top 27 bits of DSASize and bottom 5 bits of Flags.
157504eeddc0SDimitry Andric     uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5
157604eeddc0SDimitry Andric     DSAAndFlags |= Flags;
157704eeddc0SDimitry Andric 
157804eeddc0SDimitry Andric     // Emit entry point marker section.
157904eeddc0SDimitry Andric     OutStreamer->AddComment("XPLINK Routine Layout Entry");
158081ad6265SDimitry Andric     OutStreamer->emitLabel(CurrentFnEPMarkerSym);
158104eeddc0SDimitry Andric     OutStreamer->AddComment("Eyecatcher 0x00C300C500C500");
158204eeddc0SDimitry Andric     OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher.
158304eeddc0SDimitry Andric     OutStreamer->AddComment("Mark Type C'1'");
158404eeddc0SDimitry Andric     OutStreamer->emitInt8(0xF1); // Mark Type.
158581ad6265SDimitry Andric     OutStreamer->AddComment("Offset to PPA1");
158681ad6265SDimitry Andric     OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym,
158781ad6265SDimitry Andric                                         4);
158804eeddc0SDimitry Andric     if (OutStreamer->isVerboseAsm()) {
158904eeddc0SDimitry Andric       OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize));
159004eeddc0SDimitry Andric       OutStreamer->AddComment("Entry Flags");
15915f757f3fSDimitry Andric       if (Flags & 0x08)
15925f757f3fSDimitry Andric         OutStreamer->AddComment("  Bit 1: 1 = Leaf function");
15935f757f3fSDimitry Andric       else
15945f757f3fSDimitry Andric         OutStreamer->AddComment("  Bit 1: 0 = Non-leaf function");
159504eeddc0SDimitry Andric       if (Flags & 0x04)
159604eeddc0SDimitry Andric         OutStreamer->AddComment("  Bit 2: 1 = Uses alloca");
159704eeddc0SDimitry Andric       else
159804eeddc0SDimitry Andric         OutStreamer->AddComment("  Bit 2: 0 = Does not use alloca");
159904eeddc0SDimitry Andric     }
160004eeddc0SDimitry Andric     OutStreamer->emitInt32(DSAAndFlags);
160104eeddc0SDimitry Andric   }
160204eeddc0SDimitry Andric 
160304eeddc0SDimitry Andric   AsmPrinter::emitFunctionEntryLabel();
160404eeddc0SDimitry Andric }
160504eeddc0SDimitry Andric 
16060b57cec5SDimitry Andric // Force static initialization.
1607480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() {
16080b57cec5SDimitry Andric   RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget());
16090b57cec5SDimitry Andric }
1610