diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h --- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h +++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.h @@ -33,6 +33,18 @@ return static_cast(TS); } + /// Call type information for XPLINK. + enum class CallType { + BASR76 = 0, // b'x000' == BASR r7,r6 + BRAS7 = 1, // b'x001' == BRAS r7,ep + RESVD_2 = 2, // b'x010' + BRASL7 = 3, // b'x011' == BRASL r7,ep + RESVD_4 = 4, // b'x100' + RESVD_5 = 5, // b'x101' + BALR1415 = 6, // b'x110' == BALR r14,r15 + BASR33 = 7, // b'x111' == BASR r3,r3 + }; + public: SystemZAsmPrinter(TargetMachine &TM, std::unique_ptr Streamer) : AsmPrinter(TM, std::move(Streamer)), SM(*this) {} @@ -54,6 +66,7 @@ void emitFunctionEntryLabel() override; private: + void emitCallInformation(CallType CT); void LowerFENTRY_CALL(const MachineInstr &MI, SystemZMCInstLower &MCIL); void LowerSTACKMAP(const MachineInstr &MI); void LowerPATCHPOINT(const MachineInstr &MI, SystemZMCInstLower &Lower); diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp --- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -124,6 +124,18 @@ .addImm(0); } +// The XPLINK ABI requires that a no-op encoding the call type is emitted after +// each call to a subroutine. This information can be used by the called +// function to determine its entry point, e.g. for generating a backtrace. The +// call type is encoded as a register number in the bcr instruction. See +// enumeration CallType for the possible values. +void SystemZAsmPrinter::emitCallInformation(CallType CT) { + EmitToStreamer(*OutStreamer, + MCInstBuilder(SystemZ::BCRAsm) + .addImm(0) + .addReg(SystemZMC::GR64Regs[static_cast(CT)])); +} + void SystemZAsmPrinter::emitInstruction(const MachineInstr *MI) { SystemZMCInstLower Lower(MF->getContext(), *this); MCInst LoweredMI; @@ -234,18 +246,14 @@ .addReg(SystemZ::R7D) .addExpr(Lower.getExpr(MI->getOperand(0), MCSymbolRefExpr::VK_PLT))); - EmitToStreamer( - *OutStreamer, - MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R3D)); + emitCallInformation(CallType::BRASL7); return; case SystemZ::CallBASR_XPLINK64: EmitToStreamer(*OutStreamer, MCInstBuilder(SystemZ::BASR) .addReg(SystemZ::R7D) .addReg(MI->getOperand(0).getReg())); - EmitToStreamer( - *OutStreamer, - MCInstBuilder(SystemZ::BCRAsm).addImm(0).addReg(SystemZ::R0D)); + emitCallInformation(CallType::BASR76); return; case SystemZ::CallBRASL: diff --git a/llvm/test/CodeGen/SystemZ/call-zos-02.ll b/llvm/test/CodeGen/SystemZ/call-zos-02.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/SystemZ/call-zos-02.ll @@ -0,0 +1,17 @@ +; RUN: llc --mtriple=s390x-ibm-zos --show-mc-encoding < %s | FileCheck %s + +define internal signext i32 @caller() { +entry: + ret i32 0 +} + + +define hidden signext i32 @caller2() { +entry: +; CHECK-LABEL: caller2: +; CHECK: brasl 7, caller@PLT * encoding: [0xc0,0x75,A,A,A,A] +; CHECK-NEXT: * fixup A - offset: 2, value: caller@PLT+2, kind: FK_390_PC32DBL +; CHECK-NEXT: bcr 0, 3 * encoding: [0x07,0x03] + %call = call signext i32 @caller() + ret i32 %call +}