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