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;