Index: llvm/lib/Target/PowerPC/PPCFrameLowering.h =================================================================== --- llvm/lib/Target/PowerPC/PPCFrameLowering.h +++ llvm/lib/Target/PowerPC/PPCFrameLowering.h @@ -26,6 +26,7 @@ const unsigned FramePointerSaveOffset; const unsigned LinkageSize; const unsigned BasePointerSaveOffset; + const unsigned CRSaveOffset; /** * Find register[s] that can be used in function prologue and epilogue @@ -152,6 +153,10 @@ /// base pointer. unsigned getBasePointerSaveOffset() const { return BasePointerSaveOffset; } + /// getCRSaveOffset - Return the previous frame offset to save the + /// CR register. + unsigned getCRSaveOffset() const { return CRSaveOffset; } + /// getLinkageSize - Return the size of the PowerPC ABI linkage area. /// unsigned getLinkageSize() const { return LinkageSize; } Index: llvm/lib/Target/PowerPC/PPCFrameLowering.cpp =================================================================== --- llvm/lib/Target/PowerPC/PPCFrameLowering.cpp +++ llvm/lib/Target/PowerPC/PPCFrameLowering.cpp @@ -47,13 +47,15 @@ }; static unsigned computeReturnSaveOffset(const PPCSubtarget &STI) { - if (STI.isDarwinABI()) + if (STI.isDarwinABI() || STI.isAIXABI()) return STI.isPPC64() ? 16 : 8; // SVR4 ABI: return STI.isPPC64() ? 16 : 4; } static unsigned computeTOCSaveOffset(const PPCSubtarget &STI) { + if (STI.isAIXABI()) + return STI.isPPC64() ? 40 : 20; return STI.isELFv2ABI() ? 24 : 40; } @@ -66,7 +68,7 @@ if (STI.isDarwinABI()) return STI.isPPC64() ? -8U : -4U; - // SVR4 ABI: First slot in the general register save area. + // SVR4/AIX ABI: First slot in the general register save area. return STI.isPPC64() ? -8U : -4U; } @@ -82,12 +84,18 @@ if (STI.isDarwinABI()) return STI.isPPC64() ? -16U : -8U; - // SVR4 ABI: First slot in the general register save area. + // SVR4/AIX ABI: First slot in the general register save area. return STI.isPPC64() ? -16U : STI.getTargetMachine().isPositionIndependent() ? -12U : -8U; } +static unsigned computeCRSaveOffset(const PPCSubtarget &STI) { + if (STI.isAIXABI()) + return STI.isPPC64() ? 8 : 4; + return 8; +} + PPCFrameLowering::PPCFrameLowering(const PPCSubtarget &STI) : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, STI.getPlatformStackAlignment(), 0), @@ -95,7 +103,8 @@ TOCSaveOffset(computeTOCSaveOffset(Subtarget)), FramePointerSaveOffset(computeFramePointerSaveOffset(Subtarget)), LinkageSize(computeLinkageSize(Subtarget)), - BasePointerSaveOffset(computeBasePointerSaveOffset(STI)) {} + BasePointerSaveOffset(computeBasePointerSaveOffset(Subtarget)), + CRSaveOffset(computeCRSaveOffset(Subtarget)) {} // With the SVR4 ABI, callee-saved registers have fixed offsets on the stack. const PPCFrameLowering::SpillSlot *PPCFrameLowering::getCalleeSavedSpillSlots( @@ -781,15 +790,19 @@ bool isPPC64 = Subtarget.isPPC64(); // Get the ABI. bool isSVR4ABI = Subtarget.isSVR4ABI(); + bool isAIXABI = Subtarget.isAIXABI(); bool isELFv2ABI = Subtarget.isELFv2ABI(); - assert((Subtarget.isDarwinABI() || isSVR4ABI) && - "Currently only Darwin and SVR4 ABIs are supported for PowerPC."); + assert((Subtarget.isDarwinABI() || isSVR4ABI || isAIXABI) && + "Currently only Darwin, SVR4 and AIX ABIs are supported for " + "PowerPC."); // Scan the prolog, looking for an UPDATE_VRSAVE instruction. If we find it, // process it. if (!isSVR4ABI) for (unsigned i = 0; MBBI != MBB.end(); ++i, ++MBBI) { - if (MBBI->getOpcode() == PPC::UPDATE_VRSAVE) { + if (MBBI->getOpcode() == PPC::UPDATE_VRSAVE) { + if (isAIXABI) + report_fatal_error("VRSAVE is unimplemented on AIX"); HandleVRSaveUpdate(*MBBI, TII); break; } @@ -908,6 +921,9 @@ assert((isPPC64 || !MustSaveCR) && "Prologue CR saving supported only in 64-bit mode"); + if (MustSaveCR && isAIXABI) + report_fatal_error("Prologue CR saving is unimplemented on AIX"); + // Check if we can move the stack update instruction (stdu) down the prologue // past the callee saves. Hopefully this will avoid the situation where the // saves are waiting for the update on the store with update to complete. @@ -966,7 +982,7 @@ MIB.addReg(MustSaveCRs[i], CrState); BuildMI(MBB, MBBI, dl, TII.get(PPC::STW8)) .addReg(TempReg, getKillRegState(true)) - .addImm(8) + .addImm(getCRSaveOffset()) .addReg(SPReg); } @@ -1020,7 +1036,7 @@ assert(HasRedZone && "A red zone is always available on PPC64"); BuildMI(MBB, MBBI, dl, TII.get(PPC::STW8)) .addReg(TempReg, getKillRegState(true)) - .addImm(8) + .addImm(getCRSaveOffset()) .addReg(SPReg); } @@ -1590,7 +1606,7 @@ // is live here. assert(HasRedZone && "Expecting red zone"); BuildMI(MBB, MBBI, dl, TII.get(PPC::LWZ8), TempReg) - .addImm(8) + .addImm(getCRSaveOffset()) .addReg(SPReg); for (unsigned i = 0, e = MustSaveCRs.size(); i != e; ++i) BuildMI(MBB, MBBI, dl, TII.get(PPC::MTOCRF8), MustSaveCRs[i]) Index: llvm/test/CodeGen/PowerPC/aix-lr.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/PowerPC/aix-lr.ll @@ -0,0 +1,32 @@ +; RUN: llc -verify-machineinstrs -mtriple powerpc-ibm-aix-xcoff < %s | \ +; RUN: FileCheck --check-prefix=32BIT %s + +; RUN: llc -verify-machineinstrs -mtriple powerpc64-ibm-aix-xcoff < %s | \ +; RUN: FileCheck --check-prefix=64BIT %s + +define void @bar() { +entry: + +; 32BIT: mflr 0 +; 32BIT: stw 0, 8(1) +; 32BIT: stwu 1, -64(1) +; 32BIT: bl .foo +; 32BIT: nop +; 32BIT: addi 1, 1, 64 +; 32BIT: lwz 0, 8(1) +; 32BIT: mtlr 0 + +; 64BIT: mflr 0 +; 64BIT: std 0, 16(1) +; 64BIT: stdu 1, -112(1) +; 64BIT: bl .foo +; 64BIT: nop +; 64BIT: addi 1, 1, 112 +; 64BIT: ld 0, 16(1) +; 64BIT: mtlr 0 + + call void bitcast (void (...)* @foo to void ()*)() + ret void +} + +declare void @foo(...)