From bb9e962490e093cb33e4cda2e8c6716d843100bd Mon Sep 17 00:00:00 2001
From: Jonas Maebe <jonas@freepascal.org>
Date: Fri, 2 Jan 2009 15:36:27 +0000
Subject: [PATCH]   * fixed procvar parameter passing on ppc/sysv (by value
 instead of by     reference -- except for method procvars, for tmethod record
 compatibility)   * adapted tw11563 for corrected calling convention

git-svn-id: trunk@12475 -
---
 compiler/powerpc/cpupara.pas | 25 +++++++++++++++++++++++--
 tests/webtbs/tw11563.pp      |  7 ++++++-
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/compiler/powerpc/cpupara.pas b/compiler/powerpc/cpupara.pas
index 03a00a2b71..d1124cd26c 100644
--- a/compiler/powerpc/cpupara.pas
+++ b/compiler/powerpc/cpupara.pas
@@ -130,7 +130,12 @@ unit cpupara;
               result:=LOC_REGISTER;
             classrefdef:
               result:=LOC_REGISTER;
-            procvardef,
+            procvardef:
+              if (target_info.abi = abi_powerpc_aix) or
+                 (p.size = sizeof(pint)) then
+                result:=LOC_REGISTER
+              else
+                result:=LOC_REFERENCE;
             recorddef:
               if (target_info.abi<>abi_powerpc_aix) or
                  ((p.size >= 3) and
@@ -181,8 +186,24 @@ unit cpupara;
           variantdef,
           formaldef :
             result:=true;
-          recorddef,
+          { regular procvars must be passed by value, because you cannot pass
+            the address of a local stack location when calling e.g.
+            pthread_create with the address of a function (first of all it
+            expects the address of the function to execute and not the address
+            of a memory location containing that address, and secondly if you
+            first store the address on the stack and then pass the address of
+            this stack location, then this stack location may no longer be
+            valid when the newly started thread accesses it.
+
+            However, for "procedure of object" we must use the same calling
+            convention as for "8 byte record" due to the need for
+            interchangeability with the TMethod record type.
+          }
           procvardef :
+            result:=
+              (target_info.abi <> abi_powerpc_aix) and
+              (def.size <> sizeof(pint));
+          recorddef :
             result :=
               (target_info.abi<>abi_powerpc_aix) or
               ((varspez = vs_const) and
diff --git a/tests/webtbs/tw11563.pp b/tests/webtbs/tw11563.pp
index 010349aa36..94caf6572a 100644
--- a/tests/webtbs/tw11563.pp
+++ b/tests/webtbs/tw11563.pp
@@ -19,15 +19,20 @@ program ExecStack;
 
   begin
 {$if defined(cpupowerpc) or defined(cpupowerpc64)}
+    ret := ($4e shl 24) or ($80 shl 16) or ($00 shl 8) or $20;
+{$if defined(cpupowerpc64)}
     { can't use proc(@ret) because linux/ppc64 always expects some kind of
       trampoline
     }
-    ret := ($4e shl 24) or ($80 shl 16) or ($00 shl 8) or $20;
     asm
       la r0, ret
       mtctr r0
       bctrl
     end;
+{$else}
+    DoNothing := proc(@ret);
+    DoNothing;
+{$endif}
 {$endif}
 {$if defined(cpui386) or defined(cpux86_64)}
     ret := $C3;