From 250c0750a2ab541cb22a57490ef1c2dab64238f8 Mon Sep 17 00:00:00 2001 From: florian Date: Wed, 26 Aug 2020 21:03:42 +0000 Subject: [PATCH] * Xtensa: several issues with parameter passing of the windowed api fixed git-svn-id: trunk@46708 - --- compiler/psub.pas | 17 ++++++++ compiler/xtensa/cpupara.pas | 81 +++++++++++++------------------------ compiler/xtensa/cpupi.pas | 37 ++++++++++------- compiler/xtensa/symcpu.pas | 5 +++ 4 files changed, 72 insertions(+), 68 deletions(-) diff --git a/compiler/psub.pas b/compiler/psub.pas index 8c94a6fbd8..2ba1fb9807 100644 --- a/compiler/psub.pas +++ b/compiler/psub.pas @@ -1165,6 +1165,23 @@ implementation end; end; {$endif defined(x86) or defined(arm)} +{$if defined(xtensa)} + { On xtensa, the stack frame size can be estimated to avoid using an extra frame pointer, + in case parameters are passed on the stack. + + However, the draw back is, if the estimation fails, compilation will break later on + with an internal error, so this switch is not enabled by default yet. To overcome this, + multipass compilation of subroutines must be supported + } + if (target_info.abi=abi_xtensa_windowed) and (procdef.stack_tainting_parameter(calleeside)) then + begin + include(flags,pi_estimatestacksize); + set_first_temp_offset; + procdef.has_paraloc_info:=callnoside; + generate_parameter_info; + exit; + end; +{$endif defined(xtensa)} { set the start offset to the start of the temp area in the stack } set_first_temp_offset; end; diff --git a/compiler/xtensa/cpupara.pas b/compiler/xtensa/cpupara.pas index 76f86f2227..00b9d7bcab 100644 --- a/compiler/xtensa/cpupara.pas +++ b/compiler/xtensa/cpupara.pas @@ -43,7 +43,7 @@ unit cpupara; private { the max. register depends on the used call instruction } maxintreg : TSuperRegister; - procedure init_values(side: tcallercallee; var curintreg: tsuperregister; var cur_stack_offset: aword); + procedure init_values(p: tabstractprocdef; side: tcallercallee; var curintreg: tsuperregister; var cur_stack_offset: aword); function create_paraloc_info_intern(p : tabstractprocdef; side : tcallercallee; paras : tparalist; var curintreg : tsuperregister; var cur_stack_offset : aword; varargsparas : boolean) : longint; @@ -54,7 +54,8 @@ unit cpupara; uses cpuinfo,globals, verbose,systems, - defutil,symtable, + defutil, + symtable,symcpu, procinfo,cpupi; @@ -95,17 +96,14 @@ unit cpupara; classrefdef: result:=LOC_REGISTER; procvardef: - if (p.size = sizeof(pint)) then - result:=LOC_REGISTER - else - result:=LOC_REFERENCE; + result:=LOC_REGISTER; recorddef: - if (p.size > 4) then + if p.size>24 then result:=LOC_REFERENCE else result:=LOC_REGISTER; objectdef: - if is_object(p) then + if is_object(p) and (p.size>24) then result:=LOC_REFERENCE else result:=LOC_REGISTER; @@ -117,7 +115,7 @@ unit cpupara; filedef: result:=LOC_REGISTER; arraydef: - if is_dynamic_array(p) then + if is_dynamic_array(p) or (p.size<=24) then getparaloc:=LOC_REGISTER else result:=LOC_REFERENCE; @@ -127,12 +125,12 @@ unit cpupara; else result:=LOC_REFERENCE; variantdef: - result:=LOC_REFERENCE; + result:=LOC_REGISTER; { avoid problems with errornous definitions } errordef: result:=LOC_REGISTER; else - internalerror(2002071001); + internalerror(2020082501); end; end; @@ -150,33 +148,17 @@ unit cpupara; variantdef, formaldef : result:=true; - { 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:= - (def.size <> sizeof(pint)); recorddef : - result := (def.size > 8) or (varspez = vs_const); + result:=(varspez = vs_const); arraydef: result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or is_open_array(def) or is_array_of_const(def) or is_array_constructor(def); objectdef : - result:=is_object(def); + result:=is_object(def) and (varspez = vs_const); setdef : - result:=not is_smallset(def); + result:=(varspez = vs_const); stringdef : result:=tstringdef(def).stringtype in [st_shortstring,st_longstring]; else @@ -185,7 +167,7 @@ unit cpupara; end; - procedure tcpuparamanager.init_values(side : tcallercallee; var curintreg: tsuperregister; var cur_stack_offset: aword); + procedure tcpuparamanager.init_values(p : tabstractprocdef; side : tcallercallee; var curintreg: tsuperregister; var cur_stack_offset: aword); begin cur_stack_offset:=0; case target_info.abi of @@ -195,6 +177,8 @@ unit cpupara; begin curintreg:=RS_A2; maxintreg:=RS_A7; + if current_procinfo.framepointer=NR_STACK_POINTER_REG then + cur_stack_offset:=(p as tcpuprocdef).total_stackframe_size; end else begin @@ -287,7 +271,7 @@ unit cpupara; cur_stack_offset: aword; curintreg: tsuperregister; begin - init_values(side,curintreg,cur_stack_offset); + init_values(p,side,curintreg,cur_stack_offset); result := create_paraloc_info_intern(p,side,p.paras,curintreg,cur_stack_offset,false); @@ -363,13 +347,19 @@ unit cpupara; end; end; - loc := getparaloc(paradef); + loc:=getparaloc(paradef); + + if (loc=LOC_REGISTER) and ((maxintreg-nextintreg+1)*4