From cfd67c96dca998a9dbcd3bdafe8d8bb420f9c59d Mon Sep 17 00:00:00 2001 From: Misha Brukman Date: Fri, 29 Aug 2003 04:22:54 +0000 Subject: [PATCH] * Use alloca() to force GCC not to eliminate frame pointer * Break apart saving and restoring registers into separate functions * Instead of saving single and double FP registers, just save the double registers -- aliasing helps preserve the single FP registers as well. * Request just as much memory for a stub as we actually use git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8200 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/SparcV9/SparcV9CodeEmitter.cpp | 203 ++++++++++------------ 1 file changed, 89 insertions(+), 114 deletions(-) diff --git a/lib/Target/SparcV9/SparcV9CodeEmitter.cpp b/lib/Target/SparcV9/SparcV9CodeEmitter.cpp index 51254e21c9d..63bb7c37ad8 100644 --- a/lib/Target/SparcV9/SparcV9CodeEmitter.cpp +++ b/lib/Target/SparcV9/SparcV9CodeEmitter.cpp @@ -19,6 +19,7 @@ #include "Support/hash_set" #include "SparcInternals.h" #include "SparcV9CodeEmitter.h" +#include "Config/alloca.h" bool UltraSparc::addPassesToEmitMachineCode(FunctionPassManager &PM, MachineCodeEmitter &MCE) { @@ -75,8 +76,9 @@ namespace { private: uint64_t emitStubForFunction(Function *F); - static void SaveRestoreRegisters(); - static uint64_t CompilationCallback(); + static void SaveRegisters(uint64_t DoubleFP[]); + static void RestoreRegisters(uint64_t DoubleFP[]); + static void CompilationCallback(); uint64_t resolveFunctionReference(uint64_t RetAddr); }; @@ -92,7 +94,7 @@ namespace { /// uint64_t JITResolver::addFunctionReference(uint64_t Address, Function *F) { LazyCodeGenMap[Address] = F; - return (intptr_t)&JITResolver::SaveRestoreRegisters; + return (intptr_t)&JITResolver::CompilationCallback; } /// deleteFunctionReference - If we are emitting a far call, we already added a @@ -162,61 +164,37 @@ uint64_t JITResolver::insertFarJumpAtAddr(int64_t Target, uint64_t Addr) { return Addr; } -void JITResolver::SaveRestoreRegisters() { - uint32_t SingleFP[32]; - uint64_t DoubleFP[16]; - // FIXME: uint128_t QuadFloatRegs[..]; - uint64_t CCR, FSR, FPRS, g1, g5; - +void JITResolver::SaveRegisters(uint64_t DoubleFP[]) { #if defined(sparc) || defined(__sparc__) || defined(__sparcv9) - __asm__ __volatile__ (// Save g1 and g5 - "stx %%g1, %0;\n\t" "stx %%g5, %1;\n\t" - : "=m"(g1), "=m"(g5)); +#if 0 __asm__ __volatile__ (// Save condition-code registers "stx %%fsr, %0;\n\t" "rd %%fprs, %1;\n\t" "rd %%ccr, %2;\n\t" : "=m"(FSR), "=r"(FPRS), "=r"(CCR)); +#endif // GCC says: `asm' only allows up to thirty parameters! - __asm__ __volatile__ (// Save Single FP registers, part 1 - "st %%f0, %0;\n\t" "st %%f1, %1;\n\t" - "st %%f2, %2;\n\t" "st %%f3, %3;\n\t" - "st %%f4, %4;\n\t" "st %%f5, %5;\n\t" - "st %%f6, %6;\n\t" "st %%f7, %7;\n\t" - "st %%f8, %8;\n\t" "st %%f9, %9;\n\t" - "st %%f10, %10;\n\t" "st %%f11, %11;\n\t" - "st %%f12, %12;\n\t" "st %%f13, %13;\n\t" - "st %%f14, %14;\n\t" "st %%f15, %15;\n\t" - : "=m"(SingleFP[ 0]), "=m"(SingleFP[ 1]), - "=m"(SingleFP[ 2]), "=m"(SingleFP[ 3]), - "=m"(SingleFP[ 4]), "=m"(SingleFP[ 5]), - "=m"(SingleFP[ 6]), "=m"(SingleFP[ 7]), - "=m"(SingleFP[ 8]), "=m"(SingleFP[ 9]), - "=m"(SingleFP[10]), "=m"(SingleFP[11]), - "=m"(SingleFP[12]), "=m"(SingleFP[13]), - "=m"(SingleFP[14]), "=m"(SingleFP[15])); + __asm__ __volatile__ (// Save Single/Double FP registers, part 1 + "std %%f0, %0;\n\t" "std %%f2, %1;\n\t" + "std %%f4, %2;\n\t" "std %%f6, %3;\n\t" + "std %%f8, %4;\n\t" "std %%f10, %5;\n\t" + "std %%f12, %6;\n\t" "std %%f14, %7;\n\t" + "std %%f16, %8;\n\t" "std %%f18, %9;\n\t" + "std %%f20, %10;\n\t" "std %%f22, %11;\n\t" + "std %%f24, %12;\n\t" "std %%f26, %13;\n\t" + "std %%f28, %14;\n\t" "std %%f30, %15;\n\t" + : "=m"(DoubleFP[ 0]), "=m"(DoubleFP[ 1]), + "=m"(DoubleFP[ 2]), "=m"(DoubleFP[ 3]), + "=m"(DoubleFP[ 4]), "=m"(DoubleFP[ 5]), + "=m"(DoubleFP[ 6]), "=m"(DoubleFP[ 7]), + "=m"(DoubleFP[ 8]), "=m"(DoubleFP[ 9]), + "=m"(DoubleFP[10]), "=m"(DoubleFP[11]), + "=m"(DoubleFP[12]), "=m"(DoubleFP[13]), + "=m"(DoubleFP[14]), "=m"(DoubleFP[15])); - __asm__ __volatile__ (// Save Single FP registers, part 2 - "st %%f16, %0;\n\t" "st %%f17, %1;\n\t" - "st %%f18, %2;\n\t" "st %%f19, %3;\n\t" - "st %%f20, %4;\n\t" "st %%f21, %5;\n\t" - "st %%f22, %6;\n\t" "st %%f23, %7;\n\t" - "st %%f24, %8;\n\t" "st %%f25, %9;\n\t" - "st %%f26, %10;\n\t" "st %%f27, %11;\n\t" - "st %%f28, %12;\n\t" "st %%f29, %13;\n\t" - "st %%f30, %14;\n\t" "st %%f31, %15;\n\t" - : "=m"(SingleFP[16]), "=m"(SingleFP[17]), - "=m"(SingleFP[18]), "=m"(SingleFP[19]), - "=m"(SingleFP[20]), "=m"(SingleFP[21]), - "=m"(SingleFP[22]), "=m"(SingleFP[23]), - "=m"(SingleFP[24]), "=m"(SingleFP[25]), - "=m"(SingleFP[26]), "=m"(SingleFP[27]), - "=m"(SingleFP[28]), "=m"(SingleFP[29]), - "=m"(SingleFP[30]), "=m"(SingleFP[31])); - - __asm__ __volatile__ (// Save Double FP registers + __asm__ __volatile__ (// Save Double FP registers, part 2 "std %%f32, %0;\n\t" "std %%f34, %1;\n\t" "std %%f36, %2;\n\t" "std %%f38, %3;\n\t" "std %%f40, %4;\n\t" "std %%f42, %5;\n\t" @@ -225,71 +203,49 @@ void JITResolver::SaveRestoreRegisters() { "std %%f52, %10;\n\t" "std %%f54, %11;\n\t" "std %%f56, %12;\n\t" "std %%f58, %13;\n\t" "std %%f60, %14;\n\t" "std %%f62, %15;\n\t" - : "=m"(DoubleFP[32/2-16]), "=m"(DoubleFP[34/2-16]), - "=m"(DoubleFP[36/2-16]), "=m"(DoubleFP[38/2-16]), - "=m"(DoubleFP[40/2-16]), "=m"(DoubleFP[42/2-16]), - "=m"(DoubleFP[44/2-16]), "=m"(DoubleFP[46/2-16]), - "=m"(DoubleFP[48/2-16]), "=m"(DoubleFP[50/2-16]), - "=m"(DoubleFP[52/2-16]), "=m"(DoubleFP[54/2-16]), - "=m"(DoubleFP[56/2-16]), "=m"(DoubleFP[58/2-16]), - "=m"(DoubleFP[60/2-16]), "=m"(DoubleFP[62/2-16])); + : "=m"(DoubleFP[16]), "=m"(DoubleFP[17]), + "=m"(DoubleFP[18]), "=m"(DoubleFP[19]), + "=m"(DoubleFP[20]), "=m"(DoubleFP[21]), + "=m"(DoubleFP[22]), "=m"(DoubleFP[23]), + "=m"(DoubleFP[24]), "=m"(DoubleFP[25]), + "=m"(DoubleFP[26]), "=m"(DoubleFP[27]), + "=m"(DoubleFP[28]), "=m"(DoubleFP[29]), + "=m"(DoubleFP[30]), "=m"(DoubleFP[31])); #endif +} - // Resolve the function call - register uint64_t restoreAddr = CompilationCallback(); +void JITResolver::RestoreRegisters(uint64_t DoubleFP[]) { #if defined(sparc) || defined(__sparc__) || defined(__sparcv9) - // Set the return address to re-execute the `restore' instruction - __asm__ __volatile__ ("or %%o0, %%g0, %%i7;\n\t" - - // Restore g1 and g5 - "ldx %0, %%g1;\n\t" "ldx %1, %%g5;\n\t" - :: "m"(g1), "m"(g5)); +#if 0 __asm__ __volatile__ (// Restore condition-code registers "ldx %0, %%fsr;\n\t" "wr %1, 0, %%fprs;\n\t" "wr %2, 0, %%ccr;\n\t" :: "m"(FSR), "r"(FPRS), "r"(CCR)); +#endif // GCC says: `asm' only allows up to thirty parameters! - __asm__ __volatile__ (// Restore Single FP registers, part 1 - "ld %0, %%f0;\n\t" "ld %1, %%f1;\n\t" - "ld %2, %%f2;\n\t" "ld %3, %%f3;\n\t" - "ld %4, %%f4;\n\t" "ld %5, %%f5;\n\t" - "ld %6, %%f6;\n\t" "ld %7, %%f7;\n\t" - "ld %8, %%f8;\n\t" "ld %9, %%f9;\n\t" - "ld %10, %%f10;\n\t" "ld %11, %%f11;\n\t" - "ld %12, %%f12;\n\t" "ld %13, %%f13;\n\t" - "ld %14, %%f14;\n\t" "ld %15, %%f15;\n\t" - :: "m"(SingleFP[0]), "m"(SingleFP[1]), - "m"(SingleFP[2]), "m"(SingleFP[3]), - "m"(SingleFP[4]), "m"(SingleFP[5]), - "m"(SingleFP[6]), "m"(SingleFP[7]), - "m"(SingleFP[8]), "m"(SingleFP[9]), - "m"(SingleFP[10]), "m"(SingleFP[11]), - "m"(SingleFP[12]), "m"(SingleFP[13]), - "m"(SingleFP[14]), "m"(SingleFP[15])); + __asm__ __volatile__ (// Restore Single/Double FP registers, part 1 + "ldd %0, %%f0;\n\t" "ldd %1, %%f2;\n\t" + "ldd %2, %%f4;\n\t" "ldd %3, %%f6;\n\t" + "ldd %4, %%f8;\n\t" "ldd %5, %%f10;\n\t" + "ldd %6, %%f12;\n\t" "ldd %7, %%f14;\n\t" + "ldd %8, %%f16;\n\t" "ldd %9, %%f18;\n\t" + "ldd %10, %%f20;\n\t" "ldd %11, %%f22;\n\t" + "ldd %12, %%f24;\n\t" "ldd %13, %%f26;\n\t" + "ldd %14, %%f28;\n\t" "ldd %15, %%f30;\n\t" + :: "m"(DoubleFP[0]), "m"(DoubleFP[1]), + "m"(DoubleFP[2]), "m"(DoubleFP[3]), + "m"(DoubleFP[4]), "m"(DoubleFP[5]), + "m"(DoubleFP[6]), "m"(DoubleFP[7]), + "m"(DoubleFP[8]), "m"(DoubleFP[9]), + "m"(DoubleFP[10]), "m"(DoubleFP[11]), + "m"(DoubleFP[12]), "m"(DoubleFP[13]), + "m"(DoubleFP[14]), "m"(DoubleFP[15])); - __asm__ __volatile__ (// Restore Single FP registers, part 2 - "ld %0, %%f16;\n\t" "ld %1, %%f17;\n\t" - "ld %2, %%f18;\n\t" "ld %3, %%f19;\n\t" - "ld %4, %%f20;\n\t" "ld %5, %%f21;\n\t" - "ld %6, %%f22;\n\t" "ld %7, %%f23;\n\t" - "ld %8, %%f24;\n\t" "ld %9, %%f25;\n\t" - "ld %10, %%f26;\n\t" "ld %11, %%f27;\n\t" - "ld %12, %%f28;\n\t" "ld %13, %%f29;\n\t" - "ld %14, %%f30;\n\t" "ld %15, %%f31;\n\t" - :: "m"(SingleFP[16]), "m"(SingleFP[17]), - "m"(SingleFP[18]), "m"(SingleFP[19]), - "m"(SingleFP[20]), "m"(SingleFP[21]), - "m"(SingleFP[22]), "m"(SingleFP[23]), - "m"(SingleFP[24]), "m"(SingleFP[25]), - "m"(SingleFP[26]), "m"(SingleFP[27]), - "m"(SingleFP[28]), "m"(SingleFP[29]), - "m"(SingleFP[30]), "m"(SingleFP[31])); - - __asm__ __volatile__ (// Restore Double FP registers + __asm__ __volatile__ (// Restore Double FP registers, part 2 "ldd %0, %%f32;\n\t" "ldd %1, %%f34;\n\t" "ldd %2, %%f36;\n\t" "ldd %3, %%f38;\n\t" "ldd %4, %%f40;\n\t" "ldd %5, %%f42;\n\t" @@ -298,19 +254,25 @@ void JITResolver::SaveRestoreRegisters() { "ldd %10, %%f52;\n\t" "ldd %11, %%f54;\n\t" "ldd %12, %%f56;\n\t" "ldd %13, %%f58;\n\t" "ldd %14, %%f60;\n\t" "ldd %15, %%f62;\n\t" - :: "m"(DoubleFP[32/2-16]), "m"(DoubleFP[34/2-16]), - "m"(DoubleFP[36/2-16]), "m"(DoubleFP[38/2-16]), - "m"(DoubleFP[40/2-16]), "m"(DoubleFP[42/2-16]), - "m"(DoubleFP[44/2-16]), "m"(DoubleFP[46/2-16]), - "m"(DoubleFP[48/2-16]), "m"(DoubleFP[50/2-16]), - "m"(DoubleFP[52/2-16]), "m"(DoubleFP[54/2-16]), - "m"(DoubleFP[56/2-16]), "m"(DoubleFP[58/2-16]), - "m"(DoubleFP[60/2-16]), "m"(DoubleFP[62/2-16])); + :: "m"(DoubleFP[16]), "m"(DoubleFP[17]), + "m"(DoubleFP[18]), "m"(DoubleFP[19]), + "m"(DoubleFP[20]), "m"(DoubleFP[21]), + "m"(DoubleFP[22]), "m"(DoubleFP[23]), + "m"(DoubleFP[24]), "m"(DoubleFP[25]), + "m"(DoubleFP[26]), "m"(DoubleFP[27]), + "m"(DoubleFP[28]), "m"(DoubleFP[29]), + "m"(DoubleFP[30]), "m"(DoubleFP[31])); #endif } -uint64_t JITResolver::CompilationCallback() { - uint64_t CameFrom = (uint64_t)(intptr_t)__builtin_return_address(1); +void JITResolver::CompilationCallback() { + // Local space to save double registers + uint64_t DoubleFP[32]; + //uint64_t CCR, FSR, FPRS; + + SaveRegisters(DoubleFP); + + uint64_t CameFrom = (uint64_t)(intptr_t)__builtin_return_address(0); int64_t Target = (int64_t)TheJITResolver->resolveFunctionReference(CameFrom); DEBUG(std::cerr << "In callback! Addr=0x" << std::hex << CameFrom << "\n"); register int64_t returnAddr = 0; @@ -331,13 +293,23 @@ uint64_t JITResolver::CompilationCallback() { // farCall (7 instructions) uint64_t Offset = (LazyCallFlavor[CameFrom] == ShortCall) ? 4 : 28; uint64_t CodeBegin = CameFrom - Offset; + + // FIXME FIXME FIXME FIXME: __builtin_frame_address doesn't work if frame + // pointer elimination has been performed. Having a variable sized alloca + // disables frame pointer elimination currently, even if it's dead. This is a + // gross hack. + alloca(42+Offset); + // FIXME FIXME FIXME FIXME // Make sure that what we're about to overwrite is indeed "save" MachineInstr *SV = BuildMI(V9::SAVEi, 3).addReg(o6).addSImm(-192).addReg(o6); unsigned SaveInst = TheJITResolver->getBinaryCodeForInstr(*SV); delete SV; unsigned CodeInMem = *(unsigned*)(intptr_t)CodeBegin; - assert(CodeInMem == SaveInst && "About to overwrite smthg not a save instr!"); + if (CodeInMem != SaveInst) { + std::cerr << "About to overwrite smthg not a save instr!"; + abort(); + } DEBUG(std::cerr << "Emitting a far jump to 0x" << std::hex << Target << "\n"); TheJITResolver->insertFarJumpAtAddr(Target, CodeBegin); @@ -357,13 +329,17 @@ uint64_t JITResolver::CompilationCallback() { delete MI; #endif + RestoreRegisters(DoubleFP); + // Change the return address to reexecute the restore, then the jump However, // we can't just modify %i7 here, because we return to the function that will // restore the floating-point registers for us. Thus, we just return the value // we want it to be, and the parent will take care of setting %i7 correctly. DEBUG(std::cerr << "Callback returning the addr of restore inst: " << std::hex << (CameFrom-Offset-12) << "\n"); - return CameFrom - Offset - 12; // 8 because of call+delay, 4 more to restore +#if defined(sparc) || defined(__sparc__) || defined(__sparcv9) + __asm__ __volatile__ ("sub %%i7, %0, %%i7" : : "r" (Offset+12)); +#endif } /// emitStubForFunction - This method is used by the JIT when it needs to emit @@ -373,8 +349,7 @@ uint64_t JITResolver::CompilationCallback() { /// directly. /// uint64_t JITResolver::emitStubForFunction(Function *F) { - // FIXME: 40 is not enough... but should be - MCE.startFunctionStub(*F, 64); + MCE.startFunctionStub(*F, 44); DEBUG(std::cerr << "Emitting stub at addr: 0x" << std::hex << MCE.getCurrentPCValue() << "\n");