10b57cec5SDimitry Andric //===-- SystemZAsmPrinter.cpp - SystemZ LLVM assembly printer -------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Streams SystemZ assembly language and associated data, in the form of 100b57cec5SDimitry Andric // MCInsts and MCExprs respectively. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "SystemZAsmPrinter.h" 150b57cec5SDimitry Andric #include "MCTargetDesc/SystemZInstPrinter.h" 1606c3fb27SDimitry Andric #include "MCTargetDesc/SystemZMCExpr.h" 170b57cec5SDimitry Andric #include "SystemZConstantPoolValue.h" 180b57cec5SDimitry Andric #include "SystemZMCInstLower.h" 190b57cec5SDimitry Andric #include "TargetInfo/SystemZTargetInfo.h" 2006c3fb27SDimitry Andric #include "llvm/ADT/StringExtras.h" 21480093f4SDimitry Andric #include "llvm/BinaryFormat/ELF.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" 240b57cec5SDimitry Andric #include "llvm/IR/Mangler.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h" 260b57cec5SDimitry Andric #include "llvm/MC/MCInstBuilder.h" 27480093f4SDimitry Andric #include "llvm/MC/MCSectionELF.h" 280b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 29349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 305f757f3fSDimitry Andric #include "llvm/Support/Chrono.h" 315f757f3fSDimitry Andric #include "llvm/Support/ConvertEBCDIC.h" 325f757f3fSDimitry Andric #include "llvm/Support/FormatProviders.h" 335f757f3fSDimitry Andric #include "llvm/Support/FormatVariadic.h" 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric using namespace llvm; 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the 380b57cec5SDimitry Andric // GR64 register operands turned into GR32s. 390b57cec5SDimitry Andric static MCInst lowerRILow(const MachineInstr *MI, unsigned Opcode) { 400b57cec5SDimitry Andric if (MI->isCompare()) 410b57cec5SDimitry Andric return MCInstBuilder(Opcode) 420b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 430b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()); 440b57cec5SDimitry Andric else 450b57cec5SDimitry Andric return MCInstBuilder(Opcode) 460b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 470b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR32(MI->getOperand(1).getReg())) 480b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()); 490b57cec5SDimitry Andric } 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the 520b57cec5SDimitry Andric // GR64 register operands turned into GRH32s. 530b57cec5SDimitry Andric static MCInst lowerRIHigh(const MachineInstr *MI, unsigned Opcode) { 540b57cec5SDimitry Andric if (MI->isCompare()) 550b57cec5SDimitry Andric return MCInstBuilder(Opcode) 560b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 570b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()); 580b57cec5SDimitry Andric else 590b57cec5SDimitry Andric return MCInstBuilder(Opcode) 600b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 610b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(1).getReg())) 620b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()); 630b57cec5SDimitry Andric } 640b57cec5SDimitry Andric 650b57cec5SDimitry Andric // Return an RI instruction like MI with opcode Opcode, but with the 660b57cec5SDimitry Andric // R2 register turned into a GR64. 670b57cec5SDimitry Andric static MCInst lowerRIEfLow(const MachineInstr *MI, unsigned Opcode) { 680b57cec5SDimitry Andric return MCInstBuilder(Opcode) 690b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 700b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 710b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())) 720b57cec5SDimitry Andric .addImm(MI->getOperand(3).getImm()) 730b57cec5SDimitry Andric .addImm(MI->getOperand(4).getImm()) 740b57cec5SDimitry Andric .addImm(MI->getOperand(5).getImm()); 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) { 780b57cec5SDimitry Andric StringRef Name = "__tls_get_offset"; 790b57cec5SDimitry Andric return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name), 800b57cec5SDimitry Andric MCSymbolRefExpr::VK_PLT, 810b57cec5SDimitry Andric Context); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) { 850b57cec5SDimitry Andric StringRef Name = "_GLOBAL_OFFSET_TABLE_"; 860b57cec5SDimitry Andric return MCSymbolRefExpr::create(Context.getOrCreateSymbol(Name), 870b57cec5SDimitry Andric MCSymbolRefExpr::VK_None, 880b57cec5SDimitry Andric Context); 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric // MI is an instruction that accepts an optional alignment hint, 920b57cec5SDimitry Andric // and which was already lowered to LoweredMI. If the alignment 930b57cec5SDimitry Andric // of the original memory operand is known, update LoweredMI to 940b57cec5SDimitry Andric // an instruction with the corresponding hint set. 950b57cec5SDimitry Andric static void lowerAlignmentHint(const MachineInstr *MI, MCInst &LoweredMI, 960b57cec5SDimitry Andric unsigned Opcode) { 9781ad6265SDimitry Andric if (MI->memoperands_empty()) 980b57cec5SDimitry Andric return; 9981ad6265SDimitry Andric 10081ad6265SDimitry Andric Align Alignment = Align(16); 10181ad6265SDimitry Andric for (MachineInstr::mmo_iterator MMOI = MI->memoperands_begin(), 10281ad6265SDimitry Andric EE = MI->memoperands_end(); MMOI != EE; ++MMOI) 10381ad6265SDimitry Andric if ((*MMOI)->getAlign() < Alignment) 10481ad6265SDimitry Andric Alignment = (*MMOI)->getAlign(); 10581ad6265SDimitry Andric 1060b57cec5SDimitry Andric unsigned AlignmentHint = 0; 10781ad6265SDimitry Andric if (Alignment >= Align(16)) 1080b57cec5SDimitry Andric AlignmentHint = 4; 10981ad6265SDimitry Andric else if (Alignment >= Align(8)) 1100b57cec5SDimitry Andric AlignmentHint = 3; 1110b57cec5SDimitry Andric if (AlignmentHint == 0) 1120b57cec5SDimitry Andric return; 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric LoweredMI.setOpcode(Opcode); 1150b57cec5SDimitry Andric LoweredMI.addOperand(MCOperand::createImm(AlignmentHint)); 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric // MI loads the high part of a vector from memory. Return an instruction 1190b57cec5SDimitry Andric // that uses replicating vector load Opcode to do the same thing. 1200b57cec5SDimitry Andric static MCInst lowerSubvectorLoad(const MachineInstr *MI, unsigned Opcode) { 1210b57cec5SDimitry Andric return MCInstBuilder(Opcode) 1220b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 1230b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 1240b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 1250b57cec5SDimitry Andric .addReg(MI->getOperand(3).getReg()); 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric // MI stores the high part of a vector to memory. Return an instruction 1290b57cec5SDimitry Andric // that uses elemental vector store Opcode to do the same thing. 1300b57cec5SDimitry Andric static MCInst lowerSubvectorStore(const MachineInstr *MI, unsigned Opcode) { 1310b57cec5SDimitry Andric return MCInstBuilder(Opcode) 1320b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 1330b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 1340b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 1350b57cec5SDimitry Andric .addReg(MI->getOperand(3).getReg()) 1360b57cec5SDimitry Andric .addImm(0); 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric 13981ad6265SDimitry Andric // The XPLINK ABI requires that a no-op encoding the call type is emitted after 14081ad6265SDimitry Andric // each call to a subroutine. This information can be used by the called 14181ad6265SDimitry Andric // function to determine its entry point, e.g. for generating a backtrace. The 14281ad6265SDimitry Andric // call type is encoded as a register number in the bcr instruction. See 14381ad6265SDimitry Andric // enumeration CallType for the possible values. 14481ad6265SDimitry Andric void SystemZAsmPrinter::emitCallInformation(CallType CT) { 14581ad6265SDimitry Andric EmitToStreamer(*OutStreamer, 14681ad6265SDimitry Andric MCInstBuilder(SystemZ::BCRAsm) 14781ad6265SDimitry Andric .addImm(0) 14881ad6265SDimitry Andric .addReg(SystemZMC::GR64Regs[static_cast<unsigned>(CT)])); 14981ad6265SDimitry Andric } 15081ad6265SDimitry Andric 15106c3fb27SDimitry Andric uint32_t SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MCSymbol *Sym, 15206c3fb27SDimitry Andric unsigned SlotKind) { 15306c3fb27SDimitry Andric auto Key = std::make_pair(Sym, SlotKind); 15406c3fb27SDimitry Andric auto It = Displacements.find(Key); 15506c3fb27SDimitry Andric 15606c3fb27SDimitry Andric if (It != Displacements.end()) 15706c3fb27SDimitry Andric return (*It).second; 15806c3fb27SDimitry Andric 15906c3fb27SDimitry Andric // Determine length of descriptor. 16006c3fb27SDimitry Andric uint32_t Length; 16106c3fb27SDimitry Andric switch (SlotKind) { 16206c3fb27SDimitry Andric case SystemZII::MO_ADA_DIRECT_FUNC_DESC: 16306c3fb27SDimitry Andric Length = 2 * PointerSize; 16406c3fb27SDimitry Andric break; 16506c3fb27SDimitry Andric default: 16606c3fb27SDimitry Andric Length = PointerSize; 16706c3fb27SDimitry Andric break; 16806c3fb27SDimitry Andric } 16906c3fb27SDimitry Andric 17006c3fb27SDimitry Andric uint32_t Displacement = NextDisplacement; 17106c3fb27SDimitry Andric Displacements[std::make_pair(Sym, SlotKind)] = NextDisplacement; 17206c3fb27SDimitry Andric NextDisplacement += Length; 17306c3fb27SDimitry Andric 17406c3fb27SDimitry Andric return Displacement; 17506c3fb27SDimitry Andric } 17606c3fb27SDimitry Andric 17706c3fb27SDimitry Andric uint32_t 17806c3fb27SDimitry Andric SystemZAsmPrinter::AssociatedDataAreaTable::insert(const MachineOperand MO) { 17906c3fb27SDimitry Andric MCSymbol *Sym; 18006c3fb27SDimitry Andric if (MO.getType() == MachineOperand::MO_GlobalAddress) { 18106c3fb27SDimitry Andric const GlobalValue *GV = MO.getGlobal(); 18206c3fb27SDimitry Andric Sym = MO.getParent()->getMF()->getTarget().getSymbol(GV); 18306c3fb27SDimitry Andric assert(Sym && "No symbol"); 18406c3fb27SDimitry Andric } else if (MO.getType() == MachineOperand::MO_ExternalSymbol) { 18506c3fb27SDimitry Andric const char *SymName = MO.getSymbolName(); 18606c3fb27SDimitry Andric Sym = MO.getParent()->getMF()->getContext().getOrCreateSymbol(SymName); 18706c3fb27SDimitry Andric assert(Sym && "No symbol"); 18806c3fb27SDimitry Andric } else 18906c3fb27SDimitry Andric llvm_unreachable("Unexpected operand type"); 19006c3fb27SDimitry Andric 19106c3fb27SDimitry Andric unsigned ADAslotType = MO.getTargetFlags(); 19206c3fb27SDimitry Andric return insert(Sym, ADAslotType); 19306c3fb27SDimitry Andric } 19406c3fb27SDimitry Andric 1955ffd83dbSDimitry Andric void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { 196753f127fSDimitry Andric SystemZ_MC::verifyInstructionPredicates(MI->getOpcode(), 197753f127fSDimitry Andric getSubtargetInfo().getFeatureBits()); 198753f127fSDimitry Andric 1990b57cec5SDimitry Andric SystemZMCInstLower Lower(MF->getContext(), *this); 2000b57cec5SDimitry Andric MCInst LoweredMI; 2010b57cec5SDimitry Andric switch (MI->getOpcode()) { 2020b57cec5SDimitry Andric case SystemZ::Return: 20381ad6265SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BR) 20481ad6265SDimitry Andric .addReg(SystemZ::R14D); 20581ad6265SDimitry Andric break; 20681ad6265SDimitry Andric 20781ad6265SDimitry Andric case SystemZ::Return_XPLINK: 20881ad6265SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::B) 20981ad6265SDimitry Andric .addReg(SystemZ::R7D) 21081ad6265SDimitry Andric .addImm(2) 21181ad6265SDimitry Andric .addReg(0); 2120b57cec5SDimitry Andric break; 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric case SystemZ::CondReturn: 2150b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCR) 2160b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 2170b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2180b57cec5SDimitry Andric .addReg(SystemZ::R14D); 2190b57cec5SDimitry Andric break; 2200b57cec5SDimitry Andric 22181ad6265SDimitry Andric case SystemZ::CondReturn_XPLINK: 22281ad6265SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BC) 22381ad6265SDimitry Andric .addImm(MI->getOperand(0).getImm()) 22481ad6265SDimitry Andric .addImm(MI->getOperand(1).getImm()) 22581ad6265SDimitry Andric .addReg(SystemZ::R7D) 22681ad6265SDimitry Andric .addImm(2) 22781ad6265SDimitry Andric .addReg(0); 22881ad6265SDimitry Andric break; 22981ad6265SDimitry Andric 2300b57cec5SDimitry Andric case SystemZ::CRBReturn: 2310b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CRB) 2320b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2330b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 2340b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2350b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2360b57cec5SDimitry Andric .addImm(0); 2370b57cec5SDimitry Andric break; 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric case SystemZ::CGRBReturn: 2400b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGRB) 2410b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2420b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 2430b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2440b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2450b57cec5SDimitry Andric .addImm(0); 2460b57cec5SDimitry Andric break; 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric case SystemZ::CIBReturn: 2490b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CIB) 2500b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2510b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2520b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2530b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2540b57cec5SDimitry Andric .addImm(0); 2550b57cec5SDimitry Andric break; 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric case SystemZ::CGIBReturn: 2580b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGIB) 2590b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2600b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2610b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2620b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2630b57cec5SDimitry Andric .addImm(0); 2640b57cec5SDimitry Andric break; 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric case SystemZ::CLRBReturn: 2670b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLRB) 2680b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2690b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 2700b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2710b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2720b57cec5SDimitry Andric .addImm(0); 2730b57cec5SDimitry Andric break; 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric case SystemZ::CLGRBReturn: 2760b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGRB) 2770b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2780b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 2790b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2800b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2810b57cec5SDimitry Andric .addImm(0); 2820b57cec5SDimitry Andric break; 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric case SystemZ::CLIBReturn: 2850b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLIB) 2860b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2870b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2880b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2890b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2900b57cec5SDimitry Andric .addImm(0); 2910b57cec5SDimitry Andric break; 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric case SystemZ::CLGIBReturn: 2940b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGIB) 2950b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 2960b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 2970b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 2980b57cec5SDimitry Andric .addReg(SystemZ::R14D) 2990b57cec5SDimitry Andric .addImm(0); 3000b57cec5SDimitry Andric break; 3010b57cec5SDimitry Andric 302fe6060f1SDimitry Andric case SystemZ::CallBRASL_XPLINK64: 303fe6060f1SDimitry Andric EmitToStreamer(*OutStreamer, 304fe6060f1SDimitry Andric MCInstBuilder(SystemZ::BRASL) 305fe6060f1SDimitry Andric .addReg(SystemZ::R7D) 306fe6060f1SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), 307fe6060f1SDimitry Andric MCSymbolRefExpr::VK_PLT))); 30881ad6265SDimitry Andric emitCallInformation(CallType::BRASL7); 309fe6060f1SDimitry Andric return; 310fe6060f1SDimitry Andric 311fe6060f1SDimitry Andric case SystemZ::CallBASR_XPLINK64: 312fe6060f1SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 313fe6060f1SDimitry Andric .addReg(SystemZ::R7D) 314fe6060f1SDimitry Andric .addReg(MI->getOperand(0).getReg())); 31581ad6265SDimitry Andric emitCallInformation(CallType::BASR76); 31681ad6265SDimitry Andric return; 31781ad6265SDimitry Andric 31881ad6265SDimitry Andric case SystemZ::CallBASR_STACKEXT: 31981ad6265SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 32081ad6265SDimitry Andric .addReg(SystemZ::R3D) 32181ad6265SDimitry Andric .addReg(MI->getOperand(0).getReg())); 32281ad6265SDimitry Andric emitCallInformation(CallType::BASR33); 323fe6060f1SDimitry Andric return; 324fe6060f1SDimitry Andric 32506c3fb27SDimitry Andric case SystemZ::ADA_ENTRY_VALUE: 32606c3fb27SDimitry Andric case SystemZ::ADA_ENTRY: { 32706c3fb27SDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 32806c3fb27SDimitry Andric const SystemZInstrInfo *TII = Subtarget.getInstrInfo(); 32906c3fb27SDimitry Andric uint32_t Disp = ADATable.insert(MI->getOperand(1)); 33006c3fb27SDimitry Andric Register TargetReg = MI->getOperand(0).getReg(); 33106c3fb27SDimitry Andric 33206c3fb27SDimitry Andric Register ADAReg = MI->getOperand(2).getReg(); 33306c3fb27SDimitry Andric Disp += MI->getOperand(3).getImm(); 33406c3fb27SDimitry Andric bool LoadAddr = MI->getOpcode() == SystemZ::ADA_ENTRY; 33506c3fb27SDimitry Andric 33606c3fb27SDimitry Andric unsigned Op0 = LoadAddr ? SystemZ::LA : SystemZ::LG; 33706c3fb27SDimitry Andric unsigned Op = TII->getOpcodeForOffset(Op0, Disp); 33806c3fb27SDimitry Andric 33906c3fb27SDimitry Andric Register IndexReg = 0; 34006c3fb27SDimitry Andric if (!Op) { 34106c3fb27SDimitry Andric if (TargetReg != ADAReg) { 34206c3fb27SDimitry Andric IndexReg = TargetReg; 34306c3fb27SDimitry Andric // Use TargetReg to store displacement. 34406c3fb27SDimitry Andric EmitToStreamer( 34506c3fb27SDimitry Andric *OutStreamer, 34606c3fb27SDimitry Andric MCInstBuilder(SystemZ::LLILF).addReg(TargetReg).addImm(Disp)); 34706c3fb27SDimitry Andric } else 34806c3fb27SDimitry Andric EmitToStreamer( 34906c3fb27SDimitry Andric *OutStreamer, 35006c3fb27SDimitry Andric MCInstBuilder(SystemZ::ALGFI).addReg(TargetReg).addImm(Disp)); 35106c3fb27SDimitry Andric Disp = 0; 35206c3fb27SDimitry Andric Op = Op0; 35306c3fb27SDimitry Andric } 35406c3fb27SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(Op) 35506c3fb27SDimitry Andric .addReg(TargetReg) 3565f757f3fSDimitry Andric .addReg(ADAReg) 35706c3fb27SDimitry Andric .addImm(Disp) 3585f757f3fSDimitry Andric .addReg(IndexReg)); 35906c3fb27SDimitry Andric 36006c3fb27SDimitry Andric return; 36106c3fb27SDimitry Andric } 3620b57cec5SDimitry Andric case SystemZ::CallBRASL: 3630b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRASL) 3640b57cec5SDimitry Andric .addReg(SystemZ::R14D) 3650b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 3660b57cec5SDimitry Andric break; 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric case SystemZ::CallBASR: 3690b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BASR) 3700b57cec5SDimitry Andric .addReg(SystemZ::R14D) 3710b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()); 3720b57cec5SDimitry Andric break; 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric case SystemZ::CallJG: 3750b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::JG) 3760b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT)); 3770b57cec5SDimitry Andric break; 3780b57cec5SDimitry Andric 3790b57cec5SDimitry Andric case SystemZ::CallBRCL: 3800b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRCL) 3810b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 3820b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 3830b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(2), MCSymbolRefExpr::VK_PLT)); 3840b57cec5SDimitry Andric break; 3850b57cec5SDimitry Andric 3860b57cec5SDimitry Andric case SystemZ::CallBR: 387e8d8bef9SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BR) 388e8d8bef9SDimitry Andric .addReg(MI->getOperand(0).getReg()); 3890b57cec5SDimitry Andric break; 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric case SystemZ::CallBCR: 3920b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCR) 3930b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 3940b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 395e8d8bef9SDimitry Andric .addReg(MI->getOperand(2).getReg()); 3960b57cec5SDimitry Andric break; 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric case SystemZ::CRBCall: 3990b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CRB) 4000b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4010b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 4020b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 403e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4040b57cec5SDimitry Andric .addImm(0); 4050b57cec5SDimitry Andric break; 4060b57cec5SDimitry Andric 4070b57cec5SDimitry Andric case SystemZ::CGRBCall: 4080b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGRB) 4090b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4100b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 4110b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 412e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4130b57cec5SDimitry Andric .addImm(0); 4140b57cec5SDimitry Andric break; 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric case SystemZ::CIBCall: 4170b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CIB) 4180b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4190b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 4200b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 421e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4220b57cec5SDimitry Andric .addImm(0); 4230b57cec5SDimitry Andric break; 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric case SystemZ::CGIBCall: 4260b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CGIB) 4270b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4280b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 4290b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 430e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4310b57cec5SDimitry Andric .addImm(0); 4320b57cec5SDimitry Andric break; 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric case SystemZ::CLRBCall: 4350b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLRB) 4360b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4370b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 4380b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 439e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4400b57cec5SDimitry Andric .addImm(0); 4410b57cec5SDimitry Andric break; 4420b57cec5SDimitry Andric 4430b57cec5SDimitry Andric case SystemZ::CLGRBCall: 4440b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGRB) 4450b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4460b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 4470b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 448e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4490b57cec5SDimitry Andric .addImm(0); 4500b57cec5SDimitry Andric break; 4510b57cec5SDimitry Andric 4520b57cec5SDimitry Andric case SystemZ::CLIBCall: 4530b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLIB) 4540b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4550b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 4560b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 457e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4580b57cec5SDimitry Andric .addImm(0); 4590b57cec5SDimitry Andric break; 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric case SystemZ::CLGIBCall: 4620b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::CLGIB) 4630b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4640b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 4650b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 466e8d8bef9SDimitry Andric .addReg(MI->getOperand(3).getReg()) 4670b57cec5SDimitry Andric .addImm(0); 4680b57cec5SDimitry Andric break; 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric case SystemZ::TLS_GDCALL: 4710b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRASL) 4720b57cec5SDimitry Andric .addReg(SystemZ::R14D) 4730b57cec5SDimitry Andric .addExpr(getTLSGetOffset(MF->getContext())) 4740b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSGD)); 4750b57cec5SDimitry Andric break; 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric case SystemZ::TLS_LDCALL: 4780b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRASL) 4790b57cec5SDimitry Andric .addReg(SystemZ::R14D) 4800b57cec5SDimitry Andric .addExpr(getTLSGetOffset(MF->getContext())) 4810b57cec5SDimitry Andric .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_TLSLDM)); 4820b57cec5SDimitry Andric break; 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric case SystemZ::GOT: 4850b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::LARL) 4860b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 4870b57cec5SDimitry Andric .addExpr(getGlobalOffsetTable(MF->getContext())); 4880b57cec5SDimitry Andric break; 4890b57cec5SDimitry Andric 4900b57cec5SDimitry Andric case SystemZ::IILF64: 4910b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::IILF) 4920b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR32(MI->getOperand(0).getReg())) 4930b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()); 4940b57cec5SDimitry Andric break; 4950b57cec5SDimitry Andric 4960b57cec5SDimitry Andric case SystemZ::IIHF64: 4970b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::IIHF) 4980b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGRH32(MI->getOperand(0).getReg())) 4990b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()); 5000b57cec5SDimitry Andric break; 5010b57cec5SDimitry Andric 5020b57cec5SDimitry Andric case SystemZ::RISBHH: 5030b57cec5SDimitry Andric case SystemZ::RISBHL: 5040b57cec5SDimitry Andric LoweredMI = lowerRIEfLow(MI, SystemZ::RISBHG); 5050b57cec5SDimitry Andric break; 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric case SystemZ::RISBLH: 5080b57cec5SDimitry Andric case SystemZ::RISBLL: 5090b57cec5SDimitry Andric LoweredMI = lowerRIEfLow(MI, SystemZ::RISBLG); 5100b57cec5SDimitry Andric break; 5110b57cec5SDimitry Andric 5120b57cec5SDimitry Andric case SystemZ::VLVGP32: 5130b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLVGP) 5140b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 5150b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR64(MI->getOperand(1).getReg())) 5160b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR64(MI->getOperand(2).getReg())); 5170b57cec5SDimitry Andric break; 5180b57cec5SDimitry Andric 5190b57cec5SDimitry Andric case SystemZ::VLR32: 5200b57cec5SDimitry Andric case SystemZ::VLR64: 5210b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLR) 5220b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 5230b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())); 5240b57cec5SDimitry Andric break; 5250b57cec5SDimitry Andric 5260b57cec5SDimitry Andric case SystemZ::VL: 5270b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 5280b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VLAlign); 5290b57cec5SDimitry Andric break; 5300b57cec5SDimitry Andric 5310b57cec5SDimitry Andric case SystemZ::VST: 5320b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 5330b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTAlign); 5340b57cec5SDimitry Andric break; 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric case SystemZ::VLM: 5370b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 5380b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VLMAlign); 5390b57cec5SDimitry Andric break; 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric case SystemZ::VSTM: 5420b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 5430b57cec5SDimitry Andric lowerAlignmentHint(MI, LoweredMI, SystemZ::VSTMAlign); 5440b57cec5SDimitry Andric break; 5450b57cec5SDimitry Andric 5460b57cec5SDimitry Andric case SystemZ::VL32: 5470b57cec5SDimitry Andric LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPF); 5480b57cec5SDimitry Andric break; 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric case SystemZ::VL64: 5510b57cec5SDimitry Andric LoweredMI = lowerSubvectorLoad(MI, SystemZ::VLREPG); 5520b57cec5SDimitry Andric break; 5530b57cec5SDimitry Andric 5540b57cec5SDimitry Andric case SystemZ::VST32: 5550b57cec5SDimitry Andric LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEF); 5560b57cec5SDimitry Andric break; 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric case SystemZ::VST64: 5590b57cec5SDimitry Andric LoweredMI = lowerSubvectorStore(MI, SystemZ::VSTEG); 5600b57cec5SDimitry Andric break; 5610b57cec5SDimitry Andric 5620b57cec5SDimitry Andric case SystemZ::LFER: 5630b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLGVF) 5640b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsGR64(MI->getOperand(0).getReg())) 5650b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(1).getReg())) 5660b57cec5SDimitry Andric .addReg(0).addImm(0); 5670b57cec5SDimitry Andric break; 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric case SystemZ::LEFR: 5700b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::VLVGF) 5710b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 5720b57cec5SDimitry Andric .addReg(SystemZMC::getRegAsVR128(MI->getOperand(0).getReg())) 5730b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 5740b57cec5SDimitry Andric .addReg(0).addImm(0); 5750b57cec5SDimitry Andric break; 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric #define LOWER_LOW(NAME) \ 5780b57cec5SDimitry Andric case SystemZ::NAME##64: LoweredMI = lowerRILow(MI, SystemZ::NAME); break 5790b57cec5SDimitry Andric 5800b57cec5SDimitry Andric LOWER_LOW(IILL); 5810b57cec5SDimitry Andric LOWER_LOW(IILH); 5820b57cec5SDimitry Andric LOWER_LOW(TMLL); 5830b57cec5SDimitry Andric LOWER_LOW(TMLH); 5840b57cec5SDimitry Andric LOWER_LOW(NILL); 5850b57cec5SDimitry Andric LOWER_LOW(NILH); 5860b57cec5SDimitry Andric LOWER_LOW(NILF); 5870b57cec5SDimitry Andric LOWER_LOW(OILL); 5880b57cec5SDimitry Andric LOWER_LOW(OILH); 5890b57cec5SDimitry Andric LOWER_LOW(OILF); 5900b57cec5SDimitry Andric LOWER_LOW(XILF); 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric #undef LOWER_LOW 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric #define LOWER_HIGH(NAME) \ 5950b57cec5SDimitry Andric case SystemZ::NAME##64: LoweredMI = lowerRIHigh(MI, SystemZ::NAME); break 5960b57cec5SDimitry Andric 5970b57cec5SDimitry Andric LOWER_HIGH(IIHL); 5980b57cec5SDimitry Andric LOWER_HIGH(IIHH); 5990b57cec5SDimitry Andric LOWER_HIGH(TMHL); 6000b57cec5SDimitry Andric LOWER_HIGH(TMHH); 6010b57cec5SDimitry Andric LOWER_HIGH(NIHL); 6020b57cec5SDimitry Andric LOWER_HIGH(NIHH); 6030b57cec5SDimitry Andric LOWER_HIGH(NIHF); 6040b57cec5SDimitry Andric LOWER_HIGH(OIHL); 6050b57cec5SDimitry Andric LOWER_HIGH(OIHH); 6060b57cec5SDimitry Andric LOWER_HIGH(OIHF); 6070b57cec5SDimitry Andric LOWER_HIGH(XIHF); 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric #undef LOWER_HIGH 6100b57cec5SDimitry Andric 6110b57cec5SDimitry Andric case SystemZ::Serialize: 6120b57cec5SDimitry Andric if (MF->getSubtarget<SystemZSubtarget>().hasFastSerialization()) 6130b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 6140b57cec5SDimitry Andric .addImm(14).addReg(SystemZ::R0D); 6150b57cec5SDimitry Andric else 6160b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BCRAsm) 6170b57cec5SDimitry Andric .addImm(15).addReg(SystemZ::R0D); 6180b57cec5SDimitry Andric break; 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric // We want to emit "j .+2" for traps, jumping to the relative immediate field 6210b57cec5SDimitry Andric // of the jump instruction, which is an illegal instruction. We cannot emit a 6220b57cec5SDimitry Andric // "." symbol, so create and emit a temp label before the instruction and use 6230b57cec5SDimitry Andric // that instead. 6240b57cec5SDimitry Andric case SystemZ::Trap: { 6250b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 6265ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 6290b57cec5SDimitry Andric const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 6300b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::J) 6310b57cec5SDimitry Andric .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 6320b57cec5SDimitry Andric } 6330b57cec5SDimitry Andric break; 6340b57cec5SDimitry Andric 6350b57cec5SDimitry Andric // Conditional traps will create a branch on condition instruction that jumps 6360b57cec5SDimitry Andric // to the relative immediate field of the jump instruction. (eg. "jo .+2") 6370b57cec5SDimitry Andric case SystemZ::CondTrap: { 6380b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 6395ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric const MCSymbolRefExpr *Expr = MCSymbolRefExpr::create(DotSym, OutContext); 6420b57cec5SDimitry Andric const MCConstantExpr *ConstExpr = MCConstantExpr::create(2, OutContext); 6430b57cec5SDimitry Andric LoweredMI = MCInstBuilder(SystemZ::BRC) 6440b57cec5SDimitry Andric .addImm(MI->getOperand(0).getImm()) 6450b57cec5SDimitry Andric .addImm(MI->getOperand(1).getImm()) 6460b57cec5SDimitry Andric .addExpr(MCBinaryExpr::createAdd(Expr, ConstExpr, OutContext)); 6470b57cec5SDimitry Andric } 6480b57cec5SDimitry Andric break; 6490b57cec5SDimitry Andric 6508bcb0991SDimitry Andric case TargetOpcode::FENTRY_CALL: 6518bcb0991SDimitry Andric LowerFENTRY_CALL(*MI, Lower); 6528bcb0991SDimitry Andric return; 6538bcb0991SDimitry Andric 6540b57cec5SDimitry Andric case TargetOpcode::STACKMAP: 6550b57cec5SDimitry Andric LowerSTACKMAP(*MI); 6560b57cec5SDimitry Andric return; 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric case TargetOpcode::PATCHPOINT: 6590b57cec5SDimitry Andric LowerPATCHPOINT(*MI, Lower); 6600b57cec5SDimitry Andric return; 6610b57cec5SDimitry Andric 662fe6060f1SDimitry Andric case SystemZ::EXRL_Pseudo: { 663fe6060f1SDimitry Andric unsigned TargetInsOpc = MI->getOperand(0).getImm(); 664fe6060f1SDimitry Andric Register LenMinus1Reg = MI->getOperand(1).getReg(); 665fe6060f1SDimitry Andric Register DestReg = MI->getOperand(2).getReg(); 666fe6060f1SDimitry Andric int64_t DestDisp = MI->getOperand(3).getImm(); 667fe6060f1SDimitry Andric Register SrcReg = MI->getOperand(4).getReg(); 668fe6060f1SDimitry Andric int64_t SrcDisp = MI->getOperand(5).getImm(); 669fe6060f1SDimitry Andric 670349cc55cSDimitry Andric SystemZTargetStreamer *TS = getTargetStreamer(); 671fe6060f1SDimitry Andric MCSymbol *DotSym = nullptr; 672fe6060f1SDimitry Andric MCInst ET = MCInstBuilder(TargetInsOpc).addReg(DestReg) 673fe6060f1SDimitry Andric .addImm(DestDisp).addImm(1).addReg(SrcReg).addImm(SrcDisp); 674349cc55cSDimitry Andric SystemZTargetStreamer::MCInstSTIPair ET_STI(ET, &MF->getSubtarget()); 675349cc55cSDimitry Andric SystemZTargetStreamer::EXRLT2SymMap::iterator I = 676349cc55cSDimitry Andric TS->EXRLTargets2Sym.find(ET_STI); 677349cc55cSDimitry Andric if (I != TS->EXRLTargets2Sym.end()) 678fe6060f1SDimitry Andric DotSym = I->second; 679fe6060f1SDimitry Andric else 680349cc55cSDimitry Andric TS->EXRLTargets2Sym[ET_STI] = DotSym = OutContext.createTempSymbol(); 681fe6060f1SDimitry Andric const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 682fe6060f1SDimitry Andric EmitToStreamer( 683fe6060f1SDimitry Andric *OutStreamer, 684fe6060f1SDimitry Andric MCInstBuilder(SystemZ::EXRL).addReg(LenMinus1Reg).addExpr(Dot)); 685fe6060f1SDimitry Andric return; 686fe6060f1SDimitry Andric } 687fe6060f1SDimitry Andric 6880b57cec5SDimitry Andric default: 6890b57cec5SDimitry Andric Lower.lower(MI, LoweredMI); 6900b57cec5SDimitry Andric break; 6910b57cec5SDimitry Andric } 6920b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, LoweredMI); 6930b57cec5SDimitry Andric } 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric // Emit the largest nop instruction smaller than or equal to NumBytes 6960b57cec5SDimitry Andric // bytes. Return the size of nop emitted. 6970b57cec5SDimitry Andric static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, 6980b57cec5SDimitry Andric unsigned NumBytes, const MCSubtargetInfo &STI) { 6990b57cec5SDimitry Andric if (NumBytes < 2) { 7000b57cec5SDimitry Andric llvm_unreachable("Zero nops?"); 7010b57cec5SDimitry Andric return 0; 7020b57cec5SDimitry Andric } 7030b57cec5SDimitry Andric else if (NumBytes < 4) { 7045ffd83dbSDimitry Andric OutStreamer.emitInstruction( 7055ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D), STI); 7060b57cec5SDimitry Andric return 2; 7070b57cec5SDimitry Andric } 7080b57cec5SDimitry Andric else if (NumBytes < 6) { 7095ffd83dbSDimitry Andric OutStreamer.emitInstruction( 7105ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BCAsm).addImm(0).addReg(0).addImm(0).addReg(0), 7110b57cec5SDimitry Andric STI); 7120b57cec5SDimitry Andric return 4; 7130b57cec5SDimitry Andric } 7140b57cec5SDimitry Andric else { 7150b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 7160b57cec5SDimitry Andric const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(DotSym, OutContext); 7175ffd83dbSDimitry Andric OutStreamer.emitLabel(DotSym); 7185ffd83dbSDimitry Andric OutStreamer.emitInstruction( 7195ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BRCLAsm).addImm(0).addExpr(Dot), STI); 7200b57cec5SDimitry Andric return 6; 7210b57cec5SDimitry Andric } 7220b57cec5SDimitry Andric } 7230b57cec5SDimitry Andric 7248bcb0991SDimitry Andric void SystemZAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI, 7258bcb0991SDimitry Andric SystemZMCInstLower &Lower) { 7268bcb0991SDimitry Andric MCContext &Ctx = MF->getContext(); 727480093f4SDimitry Andric if (MF->getFunction().hasFnAttribute("mrecord-mcount")) { 728480093f4SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 72981ad6265SDimitry Andric OutStreamer->pushSection(); 73081ad6265SDimitry Andric OutStreamer->switchSection( 731480093f4SDimitry Andric Ctx.getELFSection("__mcount_loc", ELF::SHT_PROGBITS, ELF::SHF_ALLOC)); 7325ffd83dbSDimitry Andric OutStreamer->emitSymbolValue(DotSym, 8); 73381ad6265SDimitry Andric OutStreamer->popSection(); 7345ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 735480093f4SDimitry Andric } 736480093f4SDimitry Andric 737480093f4SDimitry Andric if (MF->getFunction().hasFnAttribute("mnop-mcount")) { 7388bcb0991SDimitry Andric EmitNop(Ctx, *OutStreamer, 6, getSubtargetInfo()); 7398bcb0991SDimitry Andric return; 7408bcb0991SDimitry Andric } 7418bcb0991SDimitry Andric 7428bcb0991SDimitry Andric MCSymbol *fentry = Ctx.getOrCreateSymbol("__fentry__"); 7438bcb0991SDimitry Andric const MCSymbolRefExpr *Op = 7448bcb0991SDimitry Andric MCSymbolRefExpr::create(fentry, MCSymbolRefExpr::VK_PLT, Ctx); 7455ffd83dbSDimitry Andric OutStreamer->emitInstruction( 7465ffd83dbSDimitry Andric MCInstBuilder(SystemZ::BRASL).addReg(SystemZ::R0D).addExpr(Op), 7475ffd83dbSDimitry Andric getSubtargetInfo()); 7488bcb0991SDimitry Andric } 7498bcb0991SDimitry Andric 7500b57cec5SDimitry Andric void SystemZAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) { 75181ad6265SDimitry Andric auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo(); 7520b57cec5SDimitry Andric 7530b57cec5SDimitry Andric unsigned NumNOPBytes = MI.getOperand(1).getImm(); 7540b57cec5SDimitry Andric 755480093f4SDimitry Andric auto &Ctx = OutStreamer->getContext(); 756480093f4SDimitry Andric MCSymbol *MILabel = Ctx.createTempSymbol(); 7575ffd83dbSDimitry Andric OutStreamer->emitLabel(MILabel); 758480093f4SDimitry Andric 759480093f4SDimitry Andric SM.recordStackMap(*MILabel, MI); 7600b57cec5SDimitry Andric assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!"); 7610b57cec5SDimitry Andric 7620b57cec5SDimitry Andric // Scan ahead to trim the shadow. 7630b57cec5SDimitry Andric unsigned ShadowBytes = 0; 7640b57cec5SDimitry Andric const MachineBasicBlock &MBB = *MI.getParent(); 7650b57cec5SDimitry Andric MachineBasicBlock::const_iterator MII(MI); 7660b57cec5SDimitry Andric ++MII; 7670b57cec5SDimitry Andric while (ShadowBytes < NumNOPBytes) { 7680b57cec5SDimitry Andric if (MII == MBB.end() || 7690b57cec5SDimitry Andric MII->getOpcode() == TargetOpcode::PATCHPOINT || 7700b57cec5SDimitry Andric MII->getOpcode() == TargetOpcode::STACKMAP) 7710b57cec5SDimitry Andric break; 7720b57cec5SDimitry Andric ShadowBytes += TII->getInstSizeInBytes(*MII); 7730b57cec5SDimitry Andric if (MII->isCall()) 7740b57cec5SDimitry Andric break; 7750b57cec5SDimitry Andric ++MII; 7760b57cec5SDimitry Andric } 7770b57cec5SDimitry Andric 7780b57cec5SDimitry Andric // Emit nops. 7790b57cec5SDimitry Andric while (ShadowBytes < NumNOPBytes) 7800b57cec5SDimitry Andric ShadowBytes += EmitNop(OutContext, *OutStreamer, NumNOPBytes - ShadowBytes, 7810b57cec5SDimitry Andric getSubtargetInfo()); 7820b57cec5SDimitry Andric } 7830b57cec5SDimitry Andric 7840b57cec5SDimitry Andric // Lower a patchpoint of the form: 7850b57cec5SDimitry Andric // [<def>], <id>, <numBytes>, <target>, <numArgs> 7860b57cec5SDimitry Andric void SystemZAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI, 7870b57cec5SDimitry Andric SystemZMCInstLower &Lower) { 788480093f4SDimitry Andric auto &Ctx = OutStreamer->getContext(); 789480093f4SDimitry Andric MCSymbol *MILabel = Ctx.createTempSymbol(); 7905ffd83dbSDimitry Andric OutStreamer->emitLabel(MILabel); 791480093f4SDimitry Andric 792480093f4SDimitry Andric SM.recordPatchPoint(*MILabel, MI); 7930b57cec5SDimitry Andric PatchPointOpers Opers(&MI); 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric unsigned EncodedBytes = 0; 7960b57cec5SDimitry Andric const MachineOperand &CalleeMO = Opers.getCallTarget(); 7970b57cec5SDimitry Andric 7980b57cec5SDimitry Andric if (CalleeMO.isImm()) { 7990b57cec5SDimitry Andric uint64_t CallTarget = CalleeMO.getImm(); 8000b57cec5SDimitry Andric if (CallTarget) { 8010b57cec5SDimitry Andric unsigned ScratchIdx = -1; 8020b57cec5SDimitry Andric unsigned ScratchReg = 0; 8030b57cec5SDimitry Andric do { 8040b57cec5SDimitry Andric ScratchIdx = Opers.getNextScratchIdx(ScratchIdx + 1); 8050b57cec5SDimitry Andric ScratchReg = MI.getOperand(ScratchIdx).getReg(); 8060b57cec5SDimitry Andric } while (ScratchReg == SystemZ::R0D); 8070b57cec5SDimitry Andric 8080b57cec5SDimitry Andric // Materialize the call target address 8090b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::LLILF) 8100b57cec5SDimitry Andric .addReg(ScratchReg) 8110b57cec5SDimitry Andric .addImm(CallTarget & 0xFFFFFFFF)); 8120b57cec5SDimitry Andric EncodedBytes += 6; 8130b57cec5SDimitry Andric if (CallTarget >> 32) { 8140b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::IIHF) 8150b57cec5SDimitry Andric .addReg(ScratchReg) 8160b57cec5SDimitry Andric .addImm(CallTarget >> 32)); 8170b57cec5SDimitry Andric EncodedBytes += 6; 8180b57cec5SDimitry Andric } 8190b57cec5SDimitry Andric 8200b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) 8210b57cec5SDimitry Andric .addReg(SystemZ::R14D) 8220b57cec5SDimitry Andric .addReg(ScratchReg)); 8230b57cec5SDimitry Andric EncodedBytes += 2; 8240b57cec5SDimitry Andric } 8250b57cec5SDimitry Andric } else if (CalleeMO.isGlobal()) { 8260b57cec5SDimitry Andric const MCExpr *Expr = Lower.getExpr(CalleeMO, MCSymbolRefExpr::VK_PLT); 8270b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BRASL) 8280b57cec5SDimitry Andric .addReg(SystemZ::R14D) 8290b57cec5SDimitry Andric .addExpr(Expr)); 8300b57cec5SDimitry Andric EncodedBytes += 6; 8310b57cec5SDimitry Andric } 8320b57cec5SDimitry Andric 8330b57cec5SDimitry Andric // Emit padding. 8340b57cec5SDimitry Andric unsigned NumBytes = Opers.getNumPatchBytes(); 8350b57cec5SDimitry Andric assert(NumBytes >= EncodedBytes && 8360b57cec5SDimitry Andric "Patchpoint can't request size less than the length of a call."); 8370b57cec5SDimitry Andric assert((NumBytes - EncodedBytes) % 2 == 0 && 8380b57cec5SDimitry Andric "Invalid number of NOP bytes requested!"); 8390b57cec5SDimitry Andric while (EncodedBytes < NumBytes) 8400b57cec5SDimitry Andric EncodedBytes += EmitNop(OutContext, *OutStreamer, NumBytes - EncodedBytes, 8410b57cec5SDimitry Andric getSubtargetInfo()); 8420b57cec5SDimitry Andric } 8430b57cec5SDimitry Andric 844bdd1243dSDimitry Andric // The *alignment* of 128-bit vector types is different between the software 845bdd1243dSDimitry Andric // and hardware vector ABIs. If the there is an externally visible use of a 846bdd1243dSDimitry Andric // vector type in the module it should be annotated with an attribute. 847bdd1243dSDimitry Andric void SystemZAsmPrinter::emitAttributes(Module &M) { 848bdd1243dSDimitry Andric if (M.getModuleFlag("s390x-visible-vector-ABI")) { 849bdd1243dSDimitry Andric bool HasVectorFeature = 85006c3fb27SDimitry Andric TM.getMCSubtargetInfo()->hasFeature(SystemZ::FeatureVector); 851bdd1243dSDimitry Andric OutStreamer->emitGNUAttribute(8, HasVectorFeature ? 2 : 1); 852bdd1243dSDimitry Andric } 853bdd1243dSDimitry Andric } 854bdd1243dSDimitry Andric 8550b57cec5SDimitry Andric // Convert a SystemZ-specific constant pool modifier into the associated 8560b57cec5SDimitry Andric // MCSymbolRefExpr variant kind. 8570b57cec5SDimitry Andric static MCSymbolRefExpr::VariantKind 8580b57cec5SDimitry Andric getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { 8590b57cec5SDimitry Andric switch (Modifier) { 8600b57cec5SDimitry Andric case SystemZCP::TLSGD: return MCSymbolRefExpr::VK_TLSGD; 8610b57cec5SDimitry Andric case SystemZCP::TLSLDM: return MCSymbolRefExpr::VK_TLSLDM; 8620b57cec5SDimitry Andric case SystemZCP::DTPOFF: return MCSymbolRefExpr::VK_DTPOFF; 8630b57cec5SDimitry Andric case SystemZCP::NTPOFF: return MCSymbolRefExpr::VK_NTPOFF; 8640b57cec5SDimitry Andric } 8650b57cec5SDimitry Andric llvm_unreachable("Invalid SystemCPModifier!"); 8660b57cec5SDimitry Andric } 8670b57cec5SDimitry Andric 8685ffd83dbSDimitry Andric void SystemZAsmPrinter::emitMachineConstantPoolValue( 8695ffd83dbSDimitry Andric MachineConstantPoolValue *MCPV) { 8700b57cec5SDimitry Andric auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV); 8710b57cec5SDimitry Andric 8720b57cec5SDimitry Andric const MCExpr *Expr = 8730b57cec5SDimitry Andric MCSymbolRefExpr::create(getSymbol(ZCPV->getGlobalValue()), 8740b57cec5SDimitry Andric getModifierVariantKind(ZCPV->getModifier()), 8750b57cec5SDimitry Andric OutContext); 8760b57cec5SDimitry Andric uint64_t Size = getDataLayout().getTypeAllocSize(ZCPV->getType()); 8770b57cec5SDimitry Andric 8785ffd83dbSDimitry Andric OutStreamer->emitValue(Expr, Size); 8790b57cec5SDimitry Andric } 8800b57cec5SDimitry Andric 881bdd1243dSDimitry Andric static void printFormattedRegName(const MCAsmInfo *MAI, unsigned RegNo, 882bdd1243dSDimitry Andric raw_ostream &OS) { 883bdd1243dSDimitry Andric const char *RegName = SystemZInstPrinter::getRegisterName(RegNo); 884bdd1243dSDimitry Andric if (MAI->getAssemblerDialect() == AD_HLASM) { 885bdd1243dSDimitry Andric // Skip register prefix so that only register number is left 886bdd1243dSDimitry Andric assert(isalpha(RegName[0]) && isdigit(RegName[1])); 887bdd1243dSDimitry Andric OS << (RegName + 1); 888bdd1243dSDimitry Andric } else 889bdd1243dSDimitry Andric OS << '%' << RegName; 890bdd1243dSDimitry Andric } 891bdd1243dSDimitry Andric 892bdd1243dSDimitry Andric static void printOperand(const MCOperand &MCOp, const MCAsmInfo *MAI, 893bdd1243dSDimitry Andric raw_ostream &OS) { 894bdd1243dSDimitry Andric if (MCOp.isReg()) { 895bdd1243dSDimitry Andric if (!MCOp.getReg()) 896bdd1243dSDimitry Andric OS << '0'; 897bdd1243dSDimitry Andric else 898bdd1243dSDimitry Andric printFormattedRegName(MAI, MCOp.getReg(), OS); 899bdd1243dSDimitry Andric } else if (MCOp.isImm()) 900bdd1243dSDimitry Andric OS << MCOp.getImm(); 901bdd1243dSDimitry Andric else if (MCOp.isExpr()) 902bdd1243dSDimitry Andric MCOp.getExpr()->print(OS, MAI); 903bdd1243dSDimitry Andric else 904bdd1243dSDimitry Andric llvm_unreachable("Invalid operand"); 905bdd1243dSDimitry Andric } 906bdd1243dSDimitry Andric 907bdd1243dSDimitry Andric static void printAddress(const MCAsmInfo *MAI, unsigned Base, 908bdd1243dSDimitry Andric const MCOperand &DispMO, unsigned Index, 909bdd1243dSDimitry Andric raw_ostream &OS) { 910bdd1243dSDimitry Andric printOperand(DispMO, MAI, OS); 911bdd1243dSDimitry Andric if (Base || Index) { 912bdd1243dSDimitry Andric OS << '('; 913bdd1243dSDimitry Andric if (Index) { 914bdd1243dSDimitry Andric printFormattedRegName(MAI, Index, OS); 915bdd1243dSDimitry Andric if (Base) 916bdd1243dSDimitry Andric OS << ','; 917bdd1243dSDimitry Andric } 918bdd1243dSDimitry Andric if (Base) 919bdd1243dSDimitry Andric printFormattedRegName(MAI, Base, OS); 920bdd1243dSDimitry Andric OS << ')'; 921bdd1243dSDimitry Andric } 922bdd1243dSDimitry Andric } 923bdd1243dSDimitry Andric 9240b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, 9250b57cec5SDimitry Andric const char *ExtraCode, 9260b57cec5SDimitry Andric raw_ostream &OS) { 927fe6060f1SDimitry Andric const MCRegisterInfo &MRI = *TM.getMCRegisterInfo(); 928fe6060f1SDimitry Andric const MachineOperand &MO = MI->getOperand(OpNo); 929fe6060f1SDimitry Andric MCOperand MCOp; 930fe6060f1SDimitry Andric if (ExtraCode) { 931fe6060f1SDimitry Andric if (ExtraCode[0] == 'N' && !ExtraCode[1] && MO.isReg() && 932fe6060f1SDimitry Andric SystemZ::GR128BitRegClass.contains(MO.getReg())) 933fe6060f1SDimitry Andric MCOp = 934fe6060f1SDimitry Andric MCOperand::createReg(MRI.getSubReg(MO.getReg(), SystemZ::subreg_l64)); 935fe6060f1SDimitry Andric else 9360b57cec5SDimitry Andric return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, OS); 937fe6060f1SDimitry Andric } else { 9380b57cec5SDimitry Andric SystemZMCInstLower Lower(MF->getContext(), *this); 939fe6060f1SDimitry Andric MCOp = Lower.lowerOperand(MO); 940fe6060f1SDimitry Andric } 941bdd1243dSDimitry Andric printOperand(MCOp, MAI, OS); 9420b57cec5SDimitry Andric return false; 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric 9450b57cec5SDimitry Andric bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 9460b57cec5SDimitry Andric unsigned OpNo, 9470b57cec5SDimitry Andric const char *ExtraCode, 9480b57cec5SDimitry Andric raw_ostream &OS) { 949349cc55cSDimitry Andric printAddress(MAI, MI->getOperand(OpNo).getReg(), 950349cc55cSDimitry Andric MCOperand::createImm(MI->getOperand(OpNo + 1).getImm()), 9510b57cec5SDimitry Andric MI->getOperand(OpNo + 2).getReg(), OS); 9520b57cec5SDimitry Andric return false; 9530b57cec5SDimitry Andric } 9540b57cec5SDimitry Andric 9555ffd83dbSDimitry Andric void SystemZAsmPrinter::emitEndOfAsmFile(Module &M) { 95606c3fb27SDimitry Andric auto TT = OutContext.getTargetTriple(); 95706c3fb27SDimitry Andric if (TT.isOSzOS()) { 95806c3fb27SDimitry Andric emitADASection(); 9595f757f3fSDimitry Andric emitIDRLSection(M); 96006c3fb27SDimitry Andric } 961bdd1243dSDimitry Andric emitAttributes(M); 9620b57cec5SDimitry Andric } 9630b57cec5SDimitry Andric 96406c3fb27SDimitry Andric void SystemZAsmPrinter::emitADASection() { 96506c3fb27SDimitry Andric OutStreamer->pushSection(); 96606c3fb27SDimitry Andric 96706c3fb27SDimitry Andric const unsigned PointerSize = getDataLayout().getPointerSize(); 96806c3fb27SDimitry Andric OutStreamer->switchSection(getObjFileLowering().getADASection()); 96906c3fb27SDimitry Andric 97006c3fb27SDimitry Andric unsigned EmittedBytes = 0; 97106c3fb27SDimitry Andric for (auto &Entry : ADATable.getTable()) { 97206c3fb27SDimitry Andric const MCSymbol *Sym; 97306c3fb27SDimitry Andric unsigned SlotKind; 97406c3fb27SDimitry Andric std::tie(Sym, SlotKind) = Entry.first; 97506c3fb27SDimitry Andric unsigned Offset = Entry.second; 97606c3fb27SDimitry Andric assert(Offset == EmittedBytes && "Offset not as expected"); 97706c3fb27SDimitry Andric (void)EmittedBytes; 97806c3fb27SDimitry Andric #define EMIT_COMMENT(Str) \ 97906c3fb27SDimitry Andric OutStreamer->AddComment(Twine("Offset ") \ 98006c3fb27SDimitry Andric .concat(utostr(Offset)) \ 98106c3fb27SDimitry Andric .concat(" " Str " ") \ 98206c3fb27SDimitry Andric .concat(Sym->getName())); 98306c3fb27SDimitry Andric switch (SlotKind) { 98406c3fb27SDimitry Andric case SystemZII::MO_ADA_DIRECT_FUNC_DESC: 98506c3fb27SDimitry Andric // Language Environment DLL logic requires function descriptors, for 98606c3fb27SDimitry Andric // imported functions, that are placed in the ADA to be 8 byte aligned. 98706c3fb27SDimitry Andric EMIT_COMMENT("function descriptor of"); 98806c3fb27SDimitry Andric OutStreamer->emitValue( 98906c3fb27SDimitry Andric SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_RCon, 99006c3fb27SDimitry Andric MCSymbolRefExpr::create(Sym, OutContext), 99106c3fb27SDimitry Andric OutContext), 99206c3fb27SDimitry Andric PointerSize); 99306c3fb27SDimitry Andric OutStreamer->emitValue( 99406c3fb27SDimitry Andric SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_VCon, 99506c3fb27SDimitry Andric MCSymbolRefExpr::create(Sym, OutContext), 99606c3fb27SDimitry Andric OutContext), 99706c3fb27SDimitry Andric PointerSize); 99806c3fb27SDimitry Andric EmittedBytes += PointerSize * 2; 99906c3fb27SDimitry Andric break; 100006c3fb27SDimitry Andric case SystemZII::MO_ADA_DATA_SYMBOL_ADDR: 100106c3fb27SDimitry Andric EMIT_COMMENT("pointer to data symbol"); 100206c3fb27SDimitry Andric OutStreamer->emitValue( 100306c3fb27SDimitry Andric SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_None, 100406c3fb27SDimitry Andric MCSymbolRefExpr::create(Sym, OutContext), 100506c3fb27SDimitry Andric OutContext), 100606c3fb27SDimitry Andric PointerSize); 100706c3fb27SDimitry Andric EmittedBytes += PointerSize; 100806c3fb27SDimitry Andric break; 100906c3fb27SDimitry Andric case SystemZII::MO_ADA_INDIRECT_FUNC_DESC: { 101006c3fb27SDimitry Andric MCSymbol *Alias = OutContext.createTempSymbol( 101106c3fb27SDimitry Andric Twine(Sym->getName()).concat("@indirect")); 101206c3fb27SDimitry Andric OutStreamer->emitAssignment(Alias, 101306c3fb27SDimitry Andric MCSymbolRefExpr::create(Sym, OutContext)); 101406c3fb27SDimitry Andric OutStreamer->emitSymbolAttribute(Alias, MCSA_IndirectSymbol); 101506c3fb27SDimitry Andric 101606c3fb27SDimitry Andric EMIT_COMMENT("pointer to function descriptor"); 101706c3fb27SDimitry Andric OutStreamer->emitValue( 101806c3fb27SDimitry Andric SystemZMCExpr::create(SystemZMCExpr::VK_SystemZ_VCon, 101906c3fb27SDimitry Andric MCSymbolRefExpr::create(Alias, OutContext), 102006c3fb27SDimitry Andric OutContext), 102106c3fb27SDimitry Andric PointerSize); 102206c3fb27SDimitry Andric EmittedBytes += PointerSize; 102306c3fb27SDimitry Andric break; 102406c3fb27SDimitry Andric } 102506c3fb27SDimitry Andric default: 102606c3fb27SDimitry Andric llvm_unreachable("Unexpected slot kind"); 102706c3fb27SDimitry Andric } 102806c3fb27SDimitry Andric #undef EMIT_COMMENT 102906c3fb27SDimitry Andric } 103006c3fb27SDimitry Andric OutStreamer->popSection(); 103106c3fb27SDimitry Andric } 103206c3fb27SDimitry Andric 10335f757f3fSDimitry Andric static std::string getProductID(Module &M) { 10345f757f3fSDimitry Andric std::string ProductID; 10355f757f3fSDimitry Andric if (auto *MD = M.getModuleFlag("zos_product_id")) 10365f757f3fSDimitry Andric ProductID = cast<MDString>(MD)->getString().str(); 10375f757f3fSDimitry Andric if (ProductID.empty()) 10385f757f3fSDimitry Andric ProductID = "LLVM"; 10395f757f3fSDimitry Andric return ProductID; 10405f757f3fSDimitry Andric } 10415f757f3fSDimitry Andric 10425f757f3fSDimitry Andric static uint32_t getProductVersion(Module &M) { 10435f757f3fSDimitry Andric if (auto *VersionVal = mdconst::extract_or_null<ConstantInt>( 10445f757f3fSDimitry Andric M.getModuleFlag("zos_product_major_version"))) 10455f757f3fSDimitry Andric return VersionVal->getZExtValue(); 10465f757f3fSDimitry Andric return LLVM_VERSION_MAJOR; 10475f757f3fSDimitry Andric } 10485f757f3fSDimitry Andric 10495f757f3fSDimitry Andric static uint32_t getProductRelease(Module &M) { 10505f757f3fSDimitry Andric if (auto *ReleaseVal = mdconst::extract_or_null<ConstantInt>( 10515f757f3fSDimitry Andric M.getModuleFlag("zos_product_minor_version"))) 10525f757f3fSDimitry Andric return ReleaseVal->getZExtValue(); 10535f757f3fSDimitry Andric return LLVM_VERSION_MINOR; 10545f757f3fSDimitry Andric } 10555f757f3fSDimitry Andric 10565f757f3fSDimitry Andric static uint32_t getProductPatch(Module &M) { 10575f757f3fSDimitry Andric if (auto *PatchVal = mdconst::extract_or_null<ConstantInt>( 10585f757f3fSDimitry Andric M.getModuleFlag("zos_product_patchlevel"))) 10595f757f3fSDimitry Andric return PatchVal->getZExtValue(); 10605f757f3fSDimitry Andric return LLVM_VERSION_PATCH; 10615f757f3fSDimitry Andric } 10625f757f3fSDimitry Andric 10635f757f3fSDimitry Andric static time_t getTranslationTime(Module &M) { 10645f757f3fSDimitry Andric std::time_t Time = 0; 10655f757f3fSDimitry Andric if (auto *Val = mdconst::extract_or_null<ConstantInt>( 10665f757f3fSDimitry Andric M.getModuleFlag("zos_translation_time"))) { 10675f757f3fSDimitry Andric long SecondsSinceEpoch = Val->getSExtValue(); 10685f757f3fSDimitry Andric Time = static_cast<time_t>(SecondsSinceEpoch); 10695f757f3fSDimitry Andric } 10705f757f3fSDimitry Andric return Time; 10715f757f3fSDimitry Andric } 10725f757f3fSDimitry Andric 10735f757f3fSDimitry Andric void SystemZAsmPrinter::emitIDRLSection(Module &M) { 10745f757f3fSDimitry Andric OutStreamer->pushSection(); 10755f757f3fSDimitry Andric OutStreamer->switchSection(getObjFileLowering().getIDRLSection()); 10765f757f3fSDimitry Andric constexpr unsigned IDRLDataLength = 30; 10775f757f3fSDimitry Andric std::time_t Time = getTranslationTime(M); 10785f757f3fSDimitry Andric 10795f757f3fSDimitry Andric uint32_t ProductVersion = getProductVersion(M); 10805f757f3fSDimitry Andric uint32_t ProductRelease = getProductRelease(M); 10815f757f3fSDimitry Andric 10825f757f3fSDimitry Andric std::string ProductID = getProductID(M); 10835f757f3fSDimitry Andric 10845f757f3fSDimitry Andric SmallString<IDRLDataLength + 1> TempStr; 10855f757f3fSDimitry Andric raw_svector_ostream O(TempStr); 10865f757f3fSDimitry Andric O << formatv("{0,-10}{1,0-2:d}{2,0-2:d}{3:%Y%m%d%H%M%S}{4,0-2}", 10875f757f3fSDimitry Andric ProductID.substr(0, 10).c_str(), ProductVersion, ProductRelease, 10885f757f3fSDimitry Andric llvm::sys::toUtcTime(Time), "0"); 10895f757f3fSDimitry Andric SmallString<IDRLDataLength> Data; 10905f757f3fSDimitry Andric ConverterEBCDIC::convertToEBCDIC(TempStr, Data); 10915f757f3fSDimitry Andric 10925f757f3fSDimitry Andric OutStreamer->emitInt8(0); // Reserved. 10935f757f3fSDimitry Andric OutStreamer->emitInt8(3); // Format. 10945f757f3fSDimitry Andric OutStreamer->emitInt16(IDRLDataLength); // Length. 10955f757f3fSDimitry Andric OutStreamer->emitBytes(Data.str()); 10965f757f3fSDimitry Andric OutStreamer->popSection(); 10975f757f3fSDimitry Andric } 10985f757f3fSDimitry Andric 109981ad6265SDimitry Andric void SystemZAsmPrinter::emitFunctionBodyEnd() { 110081ad6265SDimitry Andric if (TM.getTargetTriple().isOSzOS()) { 110181ad6265SDimitry Andric // Emit symbol for the end of function if the z/OS target streamer 110281ad6265SDimitry Andric // is used. This is needed to calculate the size of the function. 110381ad6265SDimitry Andric MCSymbol *FnEndSym = createTempSymbol("func_end"); 110481ad6265SDimitry Andric OutStreamer->emitLabel(FnEndSym); 110581ad6265SDimitry Andric 110681ad6265SDimitry Andric OutStreamer->pushSection(); 110781ad6265SDimitry Andric OutStreamer->switchSection(getObjFileLowering().getPPA1Section()); 110881ad6265SDimitry Andric emitPPA1(FnEndSym); 110981ad6265SDimitry Andric OutStreamer->popSection(); 111081ad6265SDimitry Andric 111181ad6265SDimitry Andric CurrentFnPPA1Sym = nullptr; 111281ad6265SDimitry Andric CurrentFnEPMarkerSym = nullptr; 111381ad6265SDimitry Andric } 111481ad6265SDimitry Andric } 111581ad6265SDimitry Andric 111681ad6265SDimitry Andric static void emitPPA1Flags(std::unique_ptr<MCStreamer> &OutStreamer, bool VarArg, 11175f757f3fSDimitry Andric bool StackProtector, bool FPRMask, bool VRMask, 1118*cb14a3feSDimitry Andric bool EHBlock, bool HasName) { 111981ad6265SDimitry Andric enum class PPA1Flag1 : uint8_t { 112081ad6265SDimitry Andric DSA64Bit = (0x80 >> 0), 112181ad6265SDimitry Andric VarArg = (0x80 >> 7), 112281ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(DSA64Bit) 112381ad6265SDimitry Andric }; 112481ad6265SDimitry Andric enum class PPA1Flag2 : uint8_t { 112581ad6265SDimitry Andric ExternalProcedure = (0x80 >> 0), 112681ad6265SDimitry Andric STACKPROTECTOR = (0x80 >> 3), 112781ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(ExternalProcedure) 112881ad6265SDimitry Andric }; 112981ad6265SDimitry Andric enum class PPA1Flag3 : uint8_t { 113081ad6265SDimitry Andric FPRMask = (0x80 >> 2), 113181ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(FPRMask) 113281ad6265SDimitry Andric }; 113381ad6265SDimitry Andric enum class PPA1Flag4 : uint8_t { 113481ad6265SDimitry Andric EPMOffsetPresent = (0x80 >> 0), 113581ad6265SDimitry Andric VRMask = (0x80 >> 2), 1136*cb14a3feSDimitry Andric EHBlock = (0x80 >> 3), 113781ad6265SDimitry Andric ProcedureNamePresent = (0x80 >> 7), 113881ad6265SDimitry Andric LLVM_MARK_AS_BITMASK_ENUM(EPMOffsetPresent) 113981ad6265SDimitry Andric }; 114081ad6265SDimitry Andric 114181ad6265SDimitry Andric // Declare optional section flags that can be modified. 114281ad6265SDimitry Andric auto Flags1 = PPA1Flag1(0); 114381ad6265SDimitry Andric auto Flags2 = PPA1Flag2::ExternalProcedure; 114481ad6265SDimitry Andric auto Flags3 = PPA1Flag3(0); 11455f757f3fSDimitry Andric auto Flags4 = PPA1Flag4::EPMOffsetPresent; 114681ad6265SDimitry Andric 114781ad6265SDimitry Andric Flags1 |= PPA1Flag1::DSA64Bit; 114881ad6265SDimitry Andric 114981ad6265SDimitry Andric if (VarArg) 115081ad6265SDimitry Andric Flags1 |= PPA1Flag1::VarArg; 115181ad6265SDimitry Andric 115281ad6265SDimitry Andric if (StackProtector) 115381ad6265SDimitry Andric Flags2 |= PPA1Flag2::STACKPROTECTOR; 115481ad6265SDimitry Andric 115581ad6265SDimitry Andric // SavedGPRMask, SavedFPRMask, and SavedVRMask are precomputed in. 115681ad6265SDimitry Andric if (FPRMask) 115781ad6265SDimitry Andric Flags3 |= PPA1Flag3::FPRMask; // Add emit FPR mask flag. 115881ad6265SDimitry Andric 115981ad6265SDimitry Andric if (VRMask) 116081ad6265SDimitry Andric Flags4 |= PPA1Flag4::VRMask; // Add emit VR mask flag. 116181ad6265SDimitry Andric 1162*cb14a3feSDimitry Andric if (EHBlock) 1163*cb14a3feSDimitry Andric Flags4 |= PPA1Flag4::EHBlock; // Add optional EH block. 1164*cb14a3feSDimitry Andric 11655f757f3fSDimitry Andric if (HasName) 11665f757f3fSDimitry Andric Flags4 |= PPA1Flag4::ProcedureNamePresent; // Add optional name block. 11675f757f3fSDimitry Andric 116881ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 1"); 116981ad6265SDimitry Andric if ((Flags1 & PPA1Flag1::DSA64Bit) == PPA1Flag1::DSA64Bit) 117081ad6265SDimitry Andric OutStreamer->AddComment(" Bit 0: 1 = 64-bit DSA"); 117181ad6265SDimitry Andric else 117281ad6265SDimitry Andric OutStreamer->AddComment(" Bit 0: 0 = 32-bit DSA"); 117381ad6265SDimitry Andric if ((Flags1 & PPA1Flag1::VarArg) == PPA1Flag1::VarArg) 117481ad6265SDimitry Andric OutStreamer->AddComment(" Bit 7: 1 = Vararg function"); 117581ad6265SDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>(Flags1)); // Flags 1. 117681ad6265SDimitry Andric 117781ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 2"); 117881ad6265SDimitry Andric if ((Flags2 & PPA1Flag2::ExternalProcedure) == PPA1Flag2::ExternalProcedure) 117981ad6265SDimitry Andric OutStreamer->AddComment(" Bit 0: 1 = External procedure"); 118081ad6265SDimitry Andric if ((Flags2 & PPA1Flag2::STACKPROTECTOR) == PPA1Flag2::STACKPROTECTOR) 118181ad6265SDimitry Andric OutStreamer->AddComment(" Bit 3: 1 = STACKPROTECT is enabled"); 118281ad6265SDimitry Andric else 118381ad6265SDimitry Andric OutStreamer->AddComment(" Bit 3: 0 = STACKPROTECT is not enabled"); 118481ad6265SDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>(Flags2)); // Flags 2. 118581ad6265SDimitry Andric 118681ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 3"); 118781ad6265SDimitry Andric if ((Flags3 & PPA1Flag3::FPRMask) == PPA1Flag3::FPRMask) 118881ad6265SDimitry Andric OutStreamer->AddComment(" Bit 2: 1 = FP Reg Mask is in optional area"); 118981ad6265SDimitry Andric OutStreamer->emitInt8( 119081ad6265SDimitry Andric static_cast<uint8_t>(Flags3)); // Flags 3 (optional sections). 119181ad6265SDimitry Andric 119281ad6265SDimitry Andric OutStreamer->AddComment("PPA1 Flags 4"); 119381ad6265SDimitry Andric if ((Flags4 & PPA1Flag4::VRMask) == PPA1Flag4::VRMask) 119481ad6265SDimitry Andric OutStreamer->AddComment(" Bit 2: 1 = Vector Reg Mask is in optional area"); 1195*cb14a3feSDimitry Andric if ((Flags4 & PPA1Flag4::EHBlock) == PPA1Flag4::EHBlock) 1196*cb14a3feSDimitry Andric OutStreamer->AddComment(" Bit 3: 1 = C++ EH block"); 11975f757f3fSDimitry Andric if ((Flags4 & PPA1Flag4::ProcedureNamePresent) == 11985f757f3fSDimitry Andric PPA1Flag4::ProcedureNamePresent) 11995f757f3fSDimitry Andric OutStreamer->AddComment(" Bit 7: 1 = Name Length and Name"); 120081ad6265SDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>( 120181ad6265SDimitry Andric Flags4)); // Flags 4 (optional sections, always emit these). 120281ad6265SDimitry Andric } 120381ad6265SDimitry Andric 12045f757f3fSDimitry Andric static void emitPPA1Name(std::unique_ptr<MCStreamer> &OutStreamer, 12055f757f3fSDimitry Andric StringRef OutName) { 12065f757f3fSDimitry Andric size_t NameSize = OutName.size(); 12075f757f3fSDimitry Andric uint16_t OutSize; 12085f757f3fSDimitry Andric if (NameSize < UINT16_MAX) { 12095f757f3fSDimitry Andric OutSize = static_cast<uint16_t>(NameSize); 12105f757f3fSDimitry Andric } else { 12115f757f3fSDimitry Andric OutName = OutName.substr(0, UINT16_MAX); 12125f757f3fSDimitry Andric OutSize = UINT16_MAX; 12135f757f3fSDimitry Andric } 12145f757f3fSDimitry Andric // Emit padding to ensure that the next optional field word-aligned. 12155f757f3fSDimitry Andric uint8_t ExtraZeros = 4 - ((2 + OutSize) % 4); 12165f757f3fSDimitry Andric 12175f757f3fSDimitry Andric SmallString<512> OutnameConv; 12185f757f3fSDimitry Andric ConverterEBCDIC::convertToEBCDIC(OutName, OutnameConv); 12195f757f3fSDimitry Andric OutName = OutnameConv.str(); 12205f757f3fSDimitry Andric 12215f757f3fSDimitry Andric OutStreamer->AddComment("Length of Name"); 12225f757f3fSDimitry Andric OutStreamer->emitInt16(OutSize); 12235f757f3fSDimitry Andric OutStreamer->AddComment("Name of Function"); 12245f757f3fSDimitry Andric OutStreamer->emitBytes(OutName); 12255f757f3fSDimitry Andric OutStreamer->emitZeros(ExtraZeros); 12265f757f3fSDimitry Andric } 12275f757f3fSDimitry Andric 122881ad6265SDimitry Andric void SystemZAsmPrinter::emitPPA1(MCSymbol *FnEndSym) { 12295f757f3fSDimitry Andric assert(PPA2Sym != nullptr && "PPA2 Symbol not defined"); 12305f757f3fSDimitry Andric 123181ad6265SDimitry Andric const TargetRegisterInfo *TRI = MF->getRegInfo().getTargetRegisterInfo(); 123281ad6265SDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 123381ad6265SDimitry Andric const auto TargetHasVector = Subtarget.hasVector(); 123481ad6265SDimitry Andric 123581ad6265SDimitry Andric const SystemZMachineFunctionInfo *ZFI = 123681ad6265SDimitry Andric MF->getInfo<SystemZMachineFunctionInfo>(); 123781ad6265SDimitry Andric const auto *ZFL = static_cast<const SystemZXPLINKFrameLowering *>( 123881ad6265SDimitry Andric Subtarget.getFrameLowering()); 123981ad6265SDimitry Andric const MachineFrameInfo &MFFrame = MF->getFrameInfo(); 124081ad6265SDimitry Andric 124181ad6265SDimitry Andric // Get saved GPR/FPR/VPR masks. 124281ad6265SDimitry Andric const std::vector<CalleeSavedInfo> &CSI = MFFrame.getCalleeSavedInfo(); 124381ad6265SDimitry Andric uint16_t SavedGPRMask = 0; 124481ad6265SDimitry Andric uint16_t SavedFPRMask = 0; 124581ad6265SDimitry Andric uint8_t SavedVRMask = 0; 124681ad6265SDimitry Andric int64_t OffsetFPR = 0; 124781ad6265SDimitry Andric int64_t OffsetVR = 0; 124881ad6265SDimitry Andric const int64_t TopOfStack = 124981ad6265SDimitry Andric MFFrame.getOffsetAdjustment() + MFFrame.getStackSize(); 125081ad6265SDimitry Andric 125181ad6265SDimitry Andric // Loop over the spilled registers. The CalleeSavedInfo can't be used because 125281ad6265SDimitry Andric // it does not contain all spilled registers. 125381ad6265SDimitry Andric for (unsigned I = ZFI->getSpillGPRRegs().LowGPR, 125481ad6265SDimitry Andric E = ZFI->getSpillGPRRegs().HighGPR; 125581ad6265SDimitry Andric I && E && I <= E; ++I) { 125681ad6265SDimitry Andric unsigned V = TRI->getEncodingValue((Register)I); 125781ad6265SDimitry Andric assert(V < 16 && "GPR index out of range"); 125881ad6265SDimitry Andric SavedGPRMask |= 1 << (15 - V); 125981ad6265SDimitry Andric } 126081ad6265SDimitry Andric 126181ad6265SDimitry Andric for (auto &CS : CSI) { 126281ad6265SDimitry Andric unsigned Reg = CS.getReg(); 126381ad6265SDimitry Andric unsigned I = TRI->getEncodingValue(Reg); 126481ad6265SDimitry Andric 126581ad6265SDimitry Andric if (SystemZ::FP64BitRegClass.contains(Reg)) { 126681ad6265SDimitry Andric assert(I < 16 && "FPR index out of range"); 126781ad6265SDimitry Andric SavedFPRMask |= 1 << (15 - I); 126881ad6265SDimitry Andric int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx()); 126981ad6265SDimitry Andric if (Temp < OffsetFPR) 127081ad6265SDimitry Andric OffsetFPR = Temp; 127181ad6265SDimitry Andric } else if (SystemZ::VR128BitRegClass.contains(Reg)) { 127281ad6265SDimitry Andric assert(I >= 16 && I <= 23 && "VPR index out of range"); 127381ad6265SDimitry Andric unsigned BitNum = I - 16; 127481ad6265SDimitry Andric SavedVRMask |= 1 << (7 - BitNum); 127581ad6265SDimitry Andric int64_t Temp = MFFrame.getObjectOffset(CS.getFrameIdx()); 127681ad6265SDimitry Andric if (Temp < OffsetVR) 127781ad6265SDimitry Andric OffsetVR = Temp; 127881ad6265SDimitry Andric } 127981ad6265SDimitry Andric } 128081ad6265SDimitry Andric 128181ad6265SDimitry Andric // Adjust the offset. 128281ad6265SDimitry Andric OffsetFPR += (OffsetFPR < 0) ? TopOfStack : 0; 128381ad6265SDimitry Andric OffsetVR += (OffsetVR < 0) ? TopOfStack : 0; 128481ad6265SDimitry Andric 128581ad6265SDimitry Andric // Get alloca register. 128681ad6265SDimitry Andric uint8_t FrameReg = TRI->getEncodingValue(TRI->getFrameRegister(*MF)); 128781ad6265SDimitry Andric uint8_t AllocaReg = ZFL->hasFP(*MF) ? FrameReg : 0; 128881ad6265SDimitry Andric assert(AllocaReg < 16 && "Can't have alloca register larger than 15"); 128981ad6265SDimitry Andric (void)AllocaReg; 129081ad6265SDimitry Andric 129181ad6265SDimitry Andric // Build FPR save area offset. 129281ad6265SDimitry Andric uint32_t FrameAndFPROffset = 0; 129381ad6265SDimitry Andric if (SavedFPRMask) { 129481ad6265SDimitry Andric uint64_t FPRSaveAreaOffset = OffsetFPR; 129581ad6265SDimitry Andric assert(FPRSaveAreaOffset < 0x10000000 && "Offset out of range"); 129681ad6265SDimitry Andric 129781ad6265SDimitry Andric FrameAndFPROffset = FPRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits. 129881ad6265SDimitry Andric FrameAndFPROffset |= FrameReg << 28; // Put into top 4 bits. 129981ad6265SDimitry Andric } 130081ad6265SDimitry Andric 130181ad6265SDimitry Andric // Build VR save area offset. 130281ad6265SDimitry Andric uint32_t FrameAndVROffset = 0; 130381ad6265SDimitry Andric if (TargetHasVector && SavedVRMask) { 130481ad6265SDimitry Andric uint64_t VRSaveAreaOffset = OffsetVR; 130581ad6265SDimitry Andric assert(VRSaveAreaOffset < 0x10000000 && "Offset out of range"); 130681ad6265SDimitry Andric 130781ad6265SDimitry Andric FrameAndVROffset = VRSaveAreaOffset & 0x0FFFFFFF; // Lose top 4 bits. 130881ad6265SDimitry Andric FrameAndVROffset |= FrameReg << 28; // Put into top 4 bits. 130981ad6265SDimitry Andric } 131081ad6265SDimitry Andric 131181ad6265SDimitry Andric // Emit PPA1 section. 131281ad6265SDimitry Andric OutStreamer->AddComment("PPA1"); 131381ad6265SDimitry Andric OutStreamer->emitLabel(CurrentFnPPA1Sym); 131481ad6265SDimitry Andric OutStreamer->AddComment("Version"); 131581ad6265SDimitry Andric OutStreamer->emitInt8(0x02); // Version. 131681ad6265SDimitry Andric OutStreamer->AddComment("LE Signature X'CE'"); 131781ad6265SDimitry Andric OutStreamer->emitInt8(0xCE); // CEL signature. 131881ad6265SDimitry Andric OutStreamer->AddComment("Saved GPR Mask"); 131981ad6265SDimitry Andric OutStreamer->emitInt16(SavedGPRMask); 13205f757f3fSDimitry Andric OutStreamer->AddComment("Offset to PPA2"); 13215f757f3fSDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CurrentFnPPA1Sym, 4); 13225f757f3fSDimitry Andric 1323*cb14a3feSDimitry Andric bool NeedEmitEHBlock = !MF->getLandingPads().empty(); 1324*cb14a3feSDimitry Andric 13255f757f3fSDimitry Andric bool HasName = 13265f757f3fSDimitry Andric MF->getFunction().hasName() && MF->getFunction().getName().size() > 0; 132781ad6265SDimitry Andric 132881ad6265SDimitry Andric emitPPA1Flags(OutStreamer, MF->getFunction().isVarArg(), 132981ad6265SDimitry Andric MFFrame.hasStackProtectorIndex(), SavedFPRMask != 0, 1330*cb14a3feSDimitry Andric TargetHasVector && SavedVRMask != 0, NeedEmitEHBlock, HasName); 133181ad6265SDimitry Andric 133281ad6265SDimitry Andric OutStreamer->AddComment("Length/4 of Parms"); 133381ad6265SDimitry Andric OutStreamer->emitInt16( 133406c3fb27SDimitry Andric static_cast<uint16_t>(ZFI->getSizeOfFnParams() / 4)); // Parms/4. 133581ad6265SDimitry Andric OutStreamer->AddComment("Length of Code"); 133681ad6265SDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(FnEndSym, CurrentFnEPMarkerSym, 4); 133781ad6265SDimitry Andric 133881ad6265SDimitry Andric // Emit saved FPR mask and offset to FPR save area (0x20 of flags 3). 133981ad6265SDimitry Andric if (SavedFPRMask) { 134081ad6265SDimitry Andric OutStreamer->AddComment("FPR mask"); 134181ad6265SDimitry Andric OutStreamer->emitInt16(SavedFPRMask); 134281ad6265SDimitry Andric OutStreamer->AddComment("AR mask"); 134381ad6265SDimitry Andric OutStreamer->emitInt16(0); // AR Mask, unused currently. 134481ad6265SDimitry Andric OutStreamer->AddComment("FPR Save Area Locator"); 134581ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 0-3: Register R") 134681ad6265SDimitry Andric .concat(utostr(FrameAndFPROffset >> 28)) 134781ad6265SDimitry Andric .str()); 134881ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 4-31: Offset ") 134981ad6265SDimitry Andric .concat(utostr(FrameAndFPROffset & 0x0FFFFFFF)) 135081ad6265SDimitry Andric .str()); 135181ad6265SDimitry Andric OutStreamer->emitInt32(FrameAndFPROffset); // Offset to FPR save area with 135281ad6265SDimitry Andric // register to add value to 135381ad6265SDimitry Andric // (alloca reg). 135481ad6265SDimitry Andric } 135581ad6265SDimitry Andric 135681ad6265SDimitry Andric // Emit saved VR mask to VR save area. 135781ad6265SDimitry Andric if (TargetHasVector && SavedVRMask) { 135881ad6265SDimitry Andric OutStreamer->AddComment("VR mask"); 135981ad6265SDimitry Andric OutStreamer->emitInt8(SavedVRMask); 136081ad6265SDimitry Andric OutStreamer->emitInt8(0); // Reserved. 136181ad6265SDimitry Andric OutStreamer->emitInt16(0); // Also reserved. 136281ad6265SDimitry Andric OutStreamer->AddComment("VR Save Area Locator"); 136381ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 0-3: Register R") 136481ad6265SDimitry Andric .concat(utostr(FrameAndVROffset >> 28)) 136581ad6265SDimitry Andric .str()); 136681ad6265SDimitry Andric OutStreamer->AddComment(Twine(" Bit 4-31: Offset ") 136781ad6265SDimitry Andric .concat(utostr(FrameAndVROffset & 0x0FFFFFFF)) 136881ad6265SDimitry Andric .str()); 136981ad6265SDimitry Andric OutStreamer->emitInt32(FrameAndVROffset); 137081ad6265SDimitry Andric } 137181ad6265SDimitry Andric 1372*cb14a3feSDimitry Andric // Emit C++ EH information block 1373*cb14a3feSDimitry Andric const Function *Per = nullptr; 1374*cb14a3feSDimitry Andric if (NeedEmitEHBlock) { 1375*cb14a3feSDimitry Andric Per = dyn_cast<Function>( 1376*cb14a3feSDimitry Andric MF->getFunction().getPersonalityFn()->stripPointerCasts()); 1377*cb14a3feSDimitry Andric MCSymbol *PersonalityRoutine = 1378*cb14a3feSDimitry Andric Per ? MF->getTarget().getSymbol(Per) : nullptr; 1379*cb14a3feSDimitry Andric assert(PersonalityRoutine && "Missing personality routine"); 1380*cb14a3feSDimitry Andric 1381*cb14a3feSDimitry Andric OutStreamer->AddComment("Version"); 1382*cb14a3feSDimitry Andric OutStreamer->emitInt32(1); 1383*cb14a3feSDimitry Andric OutStreamer->AddComment("Flags"); 1384*cb14a3feSDimitry Andric OutStreamer->emitInt32(0); // LSDA field is a WAS offset 1385*cb14a3feSDimitry Andric OutStreamer->AddComment("Personality routine"); 1386*cb14a3feSDimitry Andric OutStreamer->emitInt64(ADATable.insert( 1387*cb14a3feSDimitry Andric PersonalityRoutine, SystemZII::MO_ADA_INDIRECT_FUNC_DESC)); 1388*cb14a3feSDimitry Andric OutStreamer->AddComment("LSDA location"); 1389*cb14a3feSDimitry Andric MCSymbol *GCCEH = MF->getContext().getOrCreateSymbol( 1390*cb14a3feSDimitry Andric Twine("GCC_except_table") + Twine(MF->getFunctionNumber())); 1391*cb14a3feSDimitry Andric OutStreamer->emitInt64( 1392*cb14a3feSDimitry Andric ADATable.insert(GCCEH, SystemZII::MO_ADA_DATA_SYMBOL_ADDR)); 1393*cb14a3feSDimitry Andric } 1394*cb14a3feSDimitry Andric 13955f757f3fSDimitry Andric // Emit name length and name optional section (0x01 of flags 4) 13965f757f3fSDimitry Andric if (HasName) 13975f757f3fSDimitry Andric emitPPA1Name(OutStreamer, MF->getFunction().getName()); 13985f757f3fSDimitry Andric 139981ad6265SDimitry Andric // Emit offset to entry point optional section (0x80 of flags 4). 140081ad6265SDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(CurrentFnEPMarkerSym, CurrentFnPPA1Sym, 140181ad6265SDimitry Andric 4); 140281ad6265SDimitry Andric } 140381ad6265SDimitry Andric 14045f757f3fSDimitry Andric void SystemZAsmPrinter::emitStartOfAsmFile(Module &M) { 14055f757f3fSDimitry Andric if (TM.getTargetTriple().isOSzOS()) 14065f757f3fSDimitry Andric emitPPA2(M); 14075f757f3fSDimitry Andric AsmPrinter::emitStartOfAsmFile(M); 14085f757f3fSDimitry Andric } 14095f757f3fSDimitry Andric 14105f757f3fSDimitry Andric void SystemZAsmPrinter::emitPPA2(Module &M) { 14115f757f3fSDimitry Andric OutStreamer->pushSection(); 14125f757f3fSDimitry Andric OutStreamer->switchSection(getObjFileLowering().getPPA2Section()); 14135f757f3fSDimitry Andric MCContext &OutContext = OutStreamer->getContext(); 14145f757f3fSDimitry Andric // Make CELQSTRT symbol. 14155f757f3fSDimitry Andric const char *StartSymbolName = "CELQSTRT"; 14165f757f3fSDimitry Andric MCSymbol *CELQSTRT = OutContext.getOrCreateSymbol(StartSymbolName); 14175f757f3fSDimitry Andric 14185f757f3fSDimitry Andric // Create symbol and assign to class field for use in PPA1. 14195f757f3fSDimitry Andric PPA2Sym = OutContext.createTempSymbol("PPA2", false); 14205f757f3fSDimitry Andric MCSymbol *DateVersionSym = OutContext.createTempSymbol("DVS", false); 14215f757f3fSDimitry Andric 14225f757f3fSDimitry Andric std::time_t Time = getTranslationTime(M); 14235f757f3fSDimitry Andric SmallString<15> CompilationTime; // 14 + null 14245f757f3fSDimitry Andric raw_svector_ostream O(CompilationTime); 14255f757f3fSDimitry Andric O << formatv("{0:%Y%m%d%H%M%S}", llvm::sys::toUtcTime(Time)); 14265f757f3fSDimitry Andric 14275f757f3fSDimitry Andric uint32_t ProductVersion = getProductVersion(M), 14285f757f3fSDimitry Andric ProductRelease = getProductRelease(M), 14295f757f3fSDimitry Andric ProductPatch = getProductPatch(M); 14305f757f3fSDimitry Andric 14315f757f3fSDimitry Andric SmallString<7> Version; // 6 + null 14325f757f3fSDimitry Andric raw_svector_ostream ostr(Version); 14335f757f3fSDimitry Andric ostr << formatv("{0,0-2:d}{1,0-2:d}{2,0-2:d}", ProductVersion, ProductRelease, 14345f757f3fSDimitry Andric ProductPatch); 14355f757f3fSDimitry Andric 14365f757f3fSDimitry Andric // Drop 0 during conversion. 14375f757f3fSDimitry Andric SmallString<sizeof(CompilationTime) - 1> CompilationTimeStr; 14385f757f3fSDimitry Andric SmallString<sizeof(Version) - 1> VersionStr; 14395f757f3fSDimitry Andric 14405f757f3fSDimitry Andric ConverterEBCDIC::convertToEBCDIC(CompilationTime, CompilationTimeStr); 14415f757f3fSDimitry Andric ConverterEBCDIC::convertToEBCDIC(Version, VersionStr); 14425f757f3fSDimitry Andric 14435f757f3fSDimitry Andric enum class PPA2MemberId : uint8_t { 14445f757f3fSDimitry Andric // See z/OS Language Environment Vendor Interfaces v2r5, p.23, for 14455f757f3fSDimitry Andric // complete list. Only the C runtime is supported by this backend. 14465f757f3fSDimitry Andric LE_C_Runtime = 3, 14475f757f3fSDimitry Andric }; 14485f757f3fSDimitry Andric enum class PPA2MemberSubId : uint8_t { 14495f757f3fSDimitry Andric // List of languages using the LE C runtime implementation. 14505f757f3fSDimitry Andric C = 0x00, 14515f757f3fSDimitry Andric CXX = 0x01, 14525f757f3fSDimitry Andric Swift = 0x03, 14535f757f3fSDimitry Andric Go = 0x60, 14545f757f3fSDimitry Andric LLVMBasedLang = 0xe7, 14555f757f3fSDimitry Andric }; 14565f757f3fSDimitry Andric // PPA2 Flags 14575f757f3fSDimitry Andric enum class PPA2Flags : uint8_t { 14585f757f3fSDimitry Andric CompileForBinaryFloatingPoint = 0x80, 14595f757f3fSDimitry Andric CompiledWithXPLink = 0x01, 14605f757f3fSDimitry Andric CompiledUnitASCII = 0x04, 14615f757f3fSDimitry Andric HasServiceInfo = 0x20, 14625f757f3fSDimitry Andric }; 14635f757f3fSDimitry Andric 14645f757f3fSDimitry Andric PPA2MemberSubId MemberSubId = PPA2MemberSubId::LLVMBasedLang; 14655f757f3fSDimitry Andric if (auto *MD = M.getModuleFlag("zos_cu_language")) { 14665f757f3fSDimitry Andric StringRef Language = cast<MDString>(MD)->getString(); 14675f757f3fSDimitry Andric MemberSubId = StringSwitch<PPA2MemberSubId>(Language) 14685f757f3fSDimitry Andric .Case("C", PPA2MemberSubId::C) 14695f757f3fSDimitry Andric .Case("C++", PPA2MemberSubId::CXX) 14705f757f3fSDimitry Andric .Case("Swift", PPA2MemberSubId::Swift) 14715f757f3fSDimitry Andric .Case("Go", PPA2MemberSubId::Go) 14725f757f3fSDimitry Andric .Default(PPA2MemberSubId::LLVMBasedLang); 14735f757f3fSDimitry Andric } 14745f757f3fSDimitry Andric 14755f757f3fSDimitry Andric // Emit PPA2 section. 14765f757f3fSDimitry Andric OutStreamer->emitLabel(PPA2Sym); 14775f757f3fSDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>(PPA2MemberId::LE_C_Runtime)); 14785f757f3fSDimitry Andric OutStreamer->emitInt8(static_cast<uint8_t>(MemberSubId)); 14795f757f3fSDimitry Andric OutStreamer->emitInt8(0x22); // Member defined, c370_plist+c370_env 14805f757f3fSDimitry Andric OutStreamer->emitInt8(0x04); // Control level 4 (XPLink) 14815f757f3fSDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(CELQSTRT, PPA2Sym, 4); 14825f757f3fSDimitry Andric OutStreamer->emitInt32(0x00000000); 14835f757f3fSDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(DateVersionSym, PPA2Sym, 4); 14845f757f3fSDimitry Andric OutStreamer->emitInt32( 14855f757f3fSDimitry Andric 0x00000000); // Offset to main entry point, always 0 (so says TR). 14865f757f3fSDimitry Andric uint8_t Flgs = static_cast<uint8_t>(PPA2Flags::CompileForBinaryFloatingPoint); 14875f757f3fSDimitry Andric Flgs |= static_cast<uint8_t>(PPA2Flags::CompiledWithXPLink); 14885f757f3fSDimitry Andric 14895f757f3fSDimitry Andric if (auto *MD = M.getModuleFlag("zos_le_char_mode")) { 14905f757f3fSDimitry Andric const StringRef &CharMode = cast<MDString>(MD)->getString(); 14915f757f3fSDimitry Andric if (CharMode == "ascii") { 14925f757f3fSDimitry Andric Flgs |= static_cast<uint8_t>( 14935f757f3fSDimitry Andric PPA2Flags::CompiledUnitASCII); // Setting bit for ASCII char. mode. 14945f757f3fSDimitry Andric } else if (CharMode != "ebcdic") { 14955f757f3fSDimitry Andric report_fatal_error( 14965f757f3fSDimitry Andric "Only ascii or ebcdic are valid values for zos_le_char_mode " 14975f757f3fSDimitry Andric "metadata"); 14985f757f3fSDimitry Andric } 14995f757f3fSDimitry Andric } 15005f757f3fSDimitry Andric 15015f757f3fSDimitry Andric OutStreamer->emitInt8(Flgs); 15025f757f3fSDimitry Andric OutStreamer->emitInt8(0x00); // Reserved. 15035f757f3fSDimitry Andric // No MD5 signature before timestamp. 15045f757f3fSDimitry Andric // No FLOAT(AFP(VOLATILE)). 15055f757f3fSDimitry Andric // Remaining 5 flag bits reserved. 15065f757f3fSDimitry Andric OutStreamer->emitInt16(0x0000); // 16 Reserved flag bits. 15075f757f3fSDimitry Andric 15085f757f3fSDimitry Andric // Emit date and version section. 15095f757f3fSDimitry Andric OutStreamer->emitLabel(DateVersionSym); 15105f757f3fSDimitry Andric OutStreamer->emitBytes(CompilationTimeStr.str()); 15115f757f3fSDimitry Andric OutStreamer->emitBytes(VersionStr.str()); 15125f757f3fSDimitry Andric 15135f757f3fSDimitry Andric OutStreamer->emitInt16(0x0000); // Service level string length. 15145f757f3fSDimitry Andric 15155f757f3fSDimitry Andric // Emit 8 byte alignment. 15165f757f3fSDimitry Andric // Emit pointer to PPA2 label. 15175f757f3fSDimitry Andric OutStreamer->AddComment("A(PPA2-CELQSTRT)"); 15185f757f3fSDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(PPA2Sym, CELQSTRT, 8); 15195f757f3fSDimitry Andric OutStreamer->popSection(); 15205f757f3fSDimitry Andric } 15215f757f3fSDimitry Andric 152204eeddc0SDimitry Andric void SystemZAsmPrinter::emitFunctionEntryLabel() { 152381ad6265SDimitry Andric const SystemZSubtarget &Subtarget = MF->getSubtarget<SystemZSubtarget>(); 152404eeddc0SDimitry Andric 152504eeddc0SDimitry Andric if (Subtarget.getTargetTriple().isOSzOS()) { 152604eeddc0SDimitry Andric MCContext &OutContext = OutStreamer->getContext(); 152781ad6265SDimitry Andric 152881ad6265SDimitry Andric // Save information for later use. 152981ad6265SDimitry Andric std::string N(MF->getFunction().hasName() 153081ad6265SDimitry Andric ? Twine(MF->getFunction().getName()).concat("_").str() 153181ad6265SDimitry Andric : ""); 153281ad6265SDimitry Andric 153381ad6265SDimitry Andric CurrentFnEPMarkerSym = 153481ad6265SDimitry Andric OutContext.createTempSymbol(Twine("EPM_").concat(N).str(), true); 153581ad6265SDimitry Andric CurrentFnPPA1Sym = 153681ad6265SDimitry Andric OutContext.createTempSymbol(Twine("PPA1_").concat(N).str(), true); 153704eeddc0SDimitry Andric 153804eeddc0SDimitry Andric // EntryPoint Marker 153904eeddc0SDimitry Andric const MachineFrameInfo &MFFrame = MF->getFrameInfo(); 154004eeddc0SDimitry Andric bool IsUsingAlloca = MFFrame.hasVarSizedObjects(); 15415f757f3fSDimitry Andric uint32_t DSASize = MFFrame.getStackSize(); 15425f757f3fSDimitry Andric bool IsLeaf = DSASize == 0 && MFFrame.getCalleeSavedInfo().empty(); 154304eeddc0SDimitry Andric 15445f757f3fSDimitry Andric // Set Flags. 154504eeddc0SDimitry Andric uint8_t Flags = 0; 15465f757f3fSDimitry Andric if (IsLeaf) 15475f757f3fSDimitry Andric Flags |= 0x08; 154804eeddc0SDimitry Andric if (IsUsingAlloca) 154904eeddc0SDimitry Andric Flags |= 0x04; 155004eeddc0SDimitry Andric 155104eeddc0SDimitry Andric // Combine into top 27 bits of DSASize and bottom 5 bits of Flags. 155204eeddc0SDimitry Andric uint32_t DSAAndFlags = DSASize & 0xFFFFFFE0; // (x/32) << 5 155304eeddc0SDimitry Andric DSAAndFlags |= Flags; 155404eeddc0SDimitry Andric 155504eeddc0SDimitry Andric // Emit entry point marker section. 155604eeddc0SDimitry Andric OutStreamer->AddComment("XPLINK Routine Layout Entry"); 155781ad6265SDimitry Andric OutStreamer->emitLabel(CurrentFnEPMarkerSym); 155804eeddc0SDimitry Andric OutStreamer->AddComment("Eyecatcher 0x00C300C500C500"); 155904eeddc0SDimitry Andric OutStreamer->emitIntValueInHex(0x00C300C500C500, 7); // Eyecatcher. 156004eeddc0SDimitry Andric OutStreamer->AddComment("Mark Type C'1'"); 156104eeddc0SDimitry Andric OutStreamer->emitInt8(0xF1); // Mark Type. 156281ad6265SDimitry Andric OutStreamer->AddComment("Offset to PPA1"); 156381ad6265SDimitry Andric OutStreamer->emitAbsoluteSymbolDiff(CurrentFnPPA1Sym, CurrentFnEPMarkerSym, 156481ad6265SDimitry Andric 4); 156504eeddc0SDimitry Andric if (OutStreamer->isVerboseAsm()) { 156604eeddc0SDimitry Andric OutStreamer->AddComment("DSA Size 0x" + Twine::utohexstr(DSASize)); 156704eeddc0SDimitry Andric OutStreamer->AddComment("Entry Flags"); 15685f757f3fSDimitry Andric if (Flags & 0x08) 15695f757f3fSDimitry Andric OutStreamer->AddComment(" Bit 1: 1 = Leaf function"); 15705f757f3fSDimitry Andric else 15715f757f3fSDimitry Andric OutStreamer->AddComment(" Bit 1: 0 = Non-leaf function"); 157204eeddc0SDimitry Andric if (Flags & 0x04) 157304eeddc0SDimitry Andric OutStreamer->AddComment(" Bit 2: 1 = Uses alloca"); 157404eeddc0SDimitry Andric else 157504eeddc0SDimitry Andric OutStreamer->AddComment(" Bit 2: 0 = Does not use alloca"); 157604eeddc0SDimitry Andric } 157704eeddc0SDimitry Andric OutStreamer->emitInt32(DSAAndFlags); 157804eeddc0SDimitry Andric } 157904eeddc0SDimitry Andric 158004eeddc0SDimitry Andric AsmPrinter::emitFunctionEntryLabel(); 158104eeddc0SDimitry Andric } 158204eeddc0SDimitry Andric 15830b57cec5SDimitry Andric // Force static initialization. 1584480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeSystemZAsmPrinter() { 15850b57cec5SDimitry Andric RegisterAsmPrinter<SystemZAsmPrinter> X(getTheSystemZTarget()); 15860b57cec5SDimitry Andric } 1587