From 3b7e458f02c8ce71c329c7dec586c41d47520259 Mon Sep 17 00:00:00 2001 From: yury Date: Mon, 18 Jun 2007 23:23:46 +0000 Subject: [PATCH] * Properly set location of float return value if it is passed as var parameter (it is always happens for safecall functions). It fixes bugs #8523 and #8977. + test. git-svn-id: trunk@7728 - --- .gitattributes | 1 + compiler/arm/cpupara.pas | 18 ++++++++++-------- compiler/i386/cpupara.pas | 15 ++++++++------- compiler/m68k/cpupara.pas | 15 ++++++++------- compiler/powerpc/cpupara.pas | 16 ++++++++-------- compiler/powerpc64/cpupara.pas | 15 +++++++++------ compiler/sparc/cpupara.pas | 16 ++++++++-------- compiler/x86_64/cpupara.pas | 15 ++++++++------- tests/webtbs/tw8977.pp | 8 ++++++++ 9 files changed, 68 insertions(+), 51 deletions(-) create mode 100644 tests/webtbs/tw8977.pp diff --git a/.gitattributes b/.gitattributes index abf3e56719..bd9b110806 100644 --- a/.gitattributes +++ b/.gitattributes @@ -8298,6 +8298,7 @@ tests/webtbs/tw8935.pp svneol=native#text/plain tests/webtbs/tw8950.pp svneol=native#text/plain tests/webtbs/tw8975.pp svneol=native#text/plain tests/webtbs/tw8975a.pp svneol=native#text/plain +tests/webtbs/tw8977.pp svneol=native#text/plain tests/webtbs/tw9054.pp svneol=native#text/plain tests/webtbs/tw9076.pp svneol=native#text/plain tests/webtbs/tw9076a.pp svneol=native#text/plain diff --git a/compiler/arm/cpupara.pas b/compiler/arm/cpupara.pas index 798f40dd53..4fb7daee7f 100644 --- a/compiler/arm/cpupara.pas +++ b/compiler/arm/cpupara.pas @@ -435,7 +435,13 @@ unit cpupara; location_reset(p.funcretloc[side],LOC_VOID,OS_NO); exit; end; - + { Return is passed as var parameter } + if ret_in_param(p.returndef,p.proccalloption) then + begin + p.funcretloc[side].loc:=LOC_REFERENCE; + p.funcretloc[side].size:=retcgsize; + exit; + end; { Return in FPU register? } if p.returndef.typ=floatdef then begin @@ -468,8 +474,8 @@ unit cpupara; p.funcretloc[side].register:=NR_FPU_RESULT_REG; end; end - { Return in register? } - else if not ret_in_param(p.returndef,p.proccalloption) then + { Return in register } + else begin if retcgsize in [OS_64,OS_S64] then begin @@ -483,11 +489,7 @@ unit cpupara; p.funcretloc[side].loc:=LOC_REGISTER; p.funcretloc[side].register:=NR_FUNCTION_RETURN_REG; end; - end - else - begin - p.funcretloc[side].loc:=LOC_REFERENCE; - p.funcretloc[side].size:=retcgsize; + end; end; diff --git a/compiler/i386/cpupara.pas b/compiler/i386/cpupara.pas index c76754c49b..c58e36633c 100644 --- a/compiler/i386/cpupara.pas +++ b/compiler/i386/cpupara.pas @@ -328,6 +328,13 @@ unit cpupara; location_reset(p.funcretloc[side],LOC_VOID,OS_NO); exit; end; + { Return is passed as var parameter } + if ret_in_param(p.returndef,p.proccalloption) then + begin + p.funcretloc[side].loc:=LOC_REFERENCE; + p.funcretloc[side].size:=retcgsize; + exit; + end; { Return in FPU register? } if p.returndef.typ=floatdef then begin @@ -336,8 +343,7 @@ unit cpupara; p.funcretloc[side].size:=retcgsize; end else - { Return in register? } - if not ret_in_param(p.returndef,p.proccalloption) then + { Return in register } begin if retcgsize in [OS_64,OS_S64] then begin @@ -363,11 +369,6 @@ unit cpupara; else p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize)); end; - end - else - begin - p.funcretloc[side].loc:=LOC_REFERENCE; - p.funcretloc[side].size:=retcgsize; end; end; diff --git a/compiler/m68k/cpupara.pas b/compiler/m68k/cpupara.pas index cba8c12e6f..59fd81d523 100644 --- a/compiler/m68k/cpupara.pas +++ b/compiler/m68k/cpupara.pas @@ -210,6 +210,13 @@ unit cpupara; location_reset(p.funcretloc[side],LOC_VOID,OS_NO); exit; end; + { Return is passed as var parameter } + if ret_in_param(p.returndef,p.proccalloption) then + begin + p.funcretloc[side].loc:=LOC_REFERENCE; + p.funcretloc[side].size:=retcgsize; + exit; + end; { Return in FPU register? } if not(cs_fp_emulation in current_settings.moduleswitches) and (p.returndef.typ=floatdef) then begin @@ -218,8 +225,7 @@ unit cpupara; p.funcretloc[side].size:=retcgsize; end else - { Return in register? } - if not ret_in_param(p.returndef,p.proccalloption) then + { Return in register } begin if retcgsize in [OS_64,OS_S64] then begin @@ -245,11 +251,6 @@ unit cpupara; else p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize)); end; - end - else - begin - p.funcretloc[side].loc:=LOC_REFERENCE; - p.funcretloc[side].size:=retcgsize; end; end; diff --git a/compiler/powerpc/cpupara.pas b/compiler/powerpc/cpupara.pas index f0735a4437..a1f550421b 100644 --- a/compiler/powerpc/cpupara.pas +++ b/compiler/powerpc/cpupara.pas @@ -246,7 +246,13 @@ unit cpupara; p.funcretloc[side].loc:=LOC_VOID; exit; end; - + { Return is passed as var parameter } + if ret_in_param(p.returndef,p.proccalloption) then + begin + p.funcretloc[side].loc:=LOC_REFERENCE; + p.funcretloc[side].size:=retcgsize; + exit; + end; { Return in FPU register? } if p.returndef.typ=floatdef then begin @@ -255,8 +261,7 @@ unit cpupara; p.funcretloc[side].size:=retcgsize; end else - { Return in register? } - if not ret_in_param(p.returndef,p.proccalloption) then + { Return in register } begin {$ifndef cpu64bit} if retcgsize in [OS_64,OS_S64] then @@ -283,11 +288,6 @@ unit cpupara; else p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize)); end; - end - else - begin - p.funcretloc[side].loc:=LOC_REFERENCE; - p.funcretloc[side].size:=retcgsize; end; end; diff --git a/compiler/powerpc64/cpupara.pas b/compiler/powerpc64/cpupara.pas index 9377aa17be..86c6dbef8b 100644 --- a/compiler/powerpc64/cpupara.pas +++ b/compiler/powerpc64/cpupara.pas @@ -225,15 +225,21 @@ begin p.funcretloc[side].loc := LOC_VOID; exit; end; - + { Return is passed as var parameter } + if ret_in_param(p.returndef, p.proccalloption) then + begin + p.funcretloc[side].loc := LOC_REFERENCE; + p.funcretloc[side].size := retcgsize; + exit; + end; { Return in FPU register? } if p.returndef.typ = floatdef then begin p.funcretloc[side].loc := LOC_FPUREGISTER; p.funcretloc[side].register := NR_FPU_RESULT_REG; p.funcretloc[side].size := retcgsize; end else - { Return in register? } - if not ret_in_param(p.returndef, p.proccalloption) then begin + { Return in register } + begin p.funcretloc[side].loc := LOC_REGISTER; p.funcretloc[side].size := retcgsize; if side = callerside then @@ -242,9 +248,6 @@ begin else p.funcretloc[side].register := newreg(R_INTREGISTER, RS_FUNCTION_RETURN_REG, cgsize2subreg(retcgsize)); - end else begin - p.funcretloc[side].loc := LOC_REFERENCE; - p.funcretloc[side].size := retcgsize; end; end; diff --git a/compiler/sparc/cpupara.pas b/compiler/sparc/cpupara.pas index bfb5996d62..140ff45237 100644 --- a/compiler/sparc/cpupara.pas +++ b/compiler/sparc/cpupara.pas @@ -156,7 +156,13 @@ implementation p.funcretloc[side].loc:=LOC_VOID; exit; end; - + { Return is passed as var parameter } + if ret_in_param(p.returndef,p.proccalloption) then + begin + p.funcretloc[side].loc:=LOC_REFERENCE; + p.funcretloc[side].size:=retcgsize; + exit; + end; { Return in FPU register? } if p.returndef.typ=floatdef then begin @@ -167,8 +173,7 @@ implementation p.funcretloc[side].size:=retcgsize; end else - { Return in register? } - if not ret_in_param(p.returndef,p.proccalloption) then + { Return in register } begin {$ifndef cpu64bit} if retcgsize in [OS_64,OS_S64] then @@ -195,11 +200,6 @@ implementation else p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize)); end; - end - else - begin - p.funcretloc[side].loc:=LOC_REFERENCE; - p.funcretloc[side].size:=retcgsize; end; end; diff --git a/compiler/x86_64/cpupara.pas b/compiler/x86_64/cpupara.pas index 1f1c296c04..31d67a7cb6 100644 --- a/compiler/x86_64/cpupara.pas +++ b/compiler/x86_64/cpupara.pas @@ -335,6 +335,13 @@ unit cpupara; location_reset(p.funcretloc[side],LOC_VOID,OS_NO); exit; end; + { Return is passed as var parameter } + if ret_in_param(p.returndef,p.proccalloption) then + begin + p.funcretloc[side].loc:=LOC_REFERENCE; + p.funcretloc[side].size:=retcgsize; + exit; + end; { Return in FPU register? } if p.returndef.typ=floatdef then begin @@ -358,8 +365,7 @@ unit cpupara; end; end else - { Return in register? } - if not ret_in_param(p.returndef,p.proccalloption) then + { Return in register } begin p.funcretloc[side].loc:=LOC_REGISTER; p.funcretloc[side].size:=retcgsize; @@ -367,11 +373,6 @@ unit cpupara; p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RESULT_REG,cgsize2subreg(retcgsize)) else p.funcretloc[side].register:=newreg(R_INTREGISTER,RS_FUNCTION_RETURN_REG,cgsize2subreg(retcgsize)); - end - else - begin - p.funcretloc[side].loc:=LOC_REFERENCE; - p.funcretloc[side].size:=retcgsize; end; end; diff --git a/tests/webtbs/tw8977.pp b/tests/webtbs/tw8977.pp new file mode 100644 index 0000000000..20542ba58c --- /dev/null +++ b/tests/webtbs/tw8977.pp @@ -0,0 +1,8 @@ +function DoTest: double; safecall; +begin + DoTest:=1.0; +end; + +begin + writeln(DoTest); +end.