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