* let thlcg.a_call_name() return the tcgpara representing the function

result location (NR_FUNCTION_RESULT_REG is not valid on all platforms)
   o this requires passing the forced function result type (if any) to this
     method
   o a generic, basic thlcg.a_call_name() is now available that sets the
     function result location; can be called by descendants
  * the availability under all circumstances of the correct function return
    type enables g_call_system_proc() on the JVM platform to now determine
    by itself how many stack slots are removed by the call -> do so, instead
    of manually counting them (or forgetting to do so and messing up the
    maximum evaluation stack height calculations)

git-svn-id: trunk@21862 -
This commit is contained in:
Jonas Maebe 2012-07-11 08:25:58 +00:00
parent aba6923187
commit 1955255dda
8 changed files with 146 additions and 106 deletions

View File

@ -152,12 +152,12 @@ unit hlcg2ll;
} }
procedure a_loadaddr_ref_cgpara(list : TAsmList;fromsize : tdef;const r : treference;const cgpara : TCGPara);override; procedure a_loadaddr_ref_cgpara(list : TAsmList;fromsize : tdef;const r : treference;const cgpara : TCGPara);override;
procedure a_call_name(list : TAsmList;pd : tprocdef;const s : TSymStr; weak: boolean);override; function a_call_name(list : TAsmList;pd : tprocdef;const s : TSymStr; forceresdef: tdef; weak: boolean): tcgpara;override;
procedure a_call_reg(list : TAsmList;pd : tabstractprocdef;reg : tregister);override; procedure a_call_reg(list : TAsmList;pd : tabstractprocdef;reg : tregister);override;
procedure a_call_ref(list : TAsmList;pd : tabstractprocdef;const ref : treference);override; procedure a_call_ref(list : TAsmList;pd : tabstractprocdef;const ref : treference);override;
{ same as a_call_name, might be overridden on certain architectures to emit { same as a_call_name, might be overridden on certain architectures to emit
static calls without usage of a got trampoline } static calls without usage of a got trampoline }
procedure a_call_name_static(list : TAsmList;pd : tprocdef;const s : TSymStr);override; function a_call_name_static(list : TAsmList;pd : tprocdef;const s : TSymStr; forceresdef: tdef): tcgpara;override;
{ move instructions } { move instructions }
procedure a_load_const_reg(list : TAsmList;tosize : tdef;a : aint;register : tregister);override; procedure a_load_const_reg(list : TAsmList;tosize : tdef;a : aint;register : tregister);override;
@ -459,9 +459,10 @@ implementation
cg.a_loadaddr_ref_cgpara(list,r,cgpara); cg.a_loadaddr_ref_cgpara(list,r,cgpara);
end; end;
procedure thlcg2ll.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; weak: boolean); function thlcg2ll.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; forceresdef: tdef; weak: boolean): tcgpara;
begin begin
cg.a_call_name(list,s,weak); cg.a_call_name(list,s,weak);
result:=inherited;
end; end;
procedure thlcg2ll.a_call_reg(list: TAsmList; pd: tabstractprocdef; reg: tregister); procedure thlcg2ll.a_call_reg(list: TAsmList; pd: tabstractprocdef; reg: tregister);
@ -474,9 +475,10 @@ implementation
cg.a_call_ref(list,ref); cg.a_call_ref(list,ref);
end; end;
procedure thlcg2ll.a_call_name_static(list: TAsmList; pd: tprocdef; const s: TSymStr); function thlcg2ll.a_call_name_static(list: TAsmList; pd: tprocdef; const s: TSymStr; forceresdef: tdef): tcgpara;
begin begin
cg.a_call_name_static(list,s); cg.a_call_name_static(list,s);
result:=inherited a_call_name(list,pd,s,forceresdef,false);
end; end;
procedure thlcg2ll.a_load_const_reg(list: TAsmList; tosize: tdef; a: aint; register: tregister); procedure thlcg2ll.a_load_const_reg(list: TAsmList; tosize: tdef; a: aint; register: tregister);

View File

@ -191,14 +191,15 @@ unit hlcgobj;
} }
{# Emits instruction to call the method specified by symbol name. {# Emits instruction to call the method specified by symbol name.
Returns the function result location.
This routine must be overridden for each new target cpu. This routine must be overridden for each new target cpu.
} }
procedure a_call_name(list : TAsmList;pd : tprocdef;const s : TSymStr; weak: boolean);virtual;abstract; function a_call_name(list : TAsmList;pd : tprocdef;const s : TSymStr; forceresdef: tdef; weak: boolean): tcgpara;virtual;
procedure a_call_reg(list : TAsmList;pd : tabstractprocdef;reg : tregister);virtual;abstract; procedure a_call_reg(list : TAsmList;pd : tabstractprocdef;reg : tregister);virtual;abstract;
procedure a_call_ref(list : TAsmList;pd : tabstractprocdef;const ref : treference);virtual; procedure a_call_ref(list : TAsmList;pd : tabstractprocdef;const ref : treference);virtual;
{ same as a_call_name, might be overridden on certain architectures to emit { same as a_call_name, might be overridden on certain architectures to emit
static calls without usage of a got trampoline } static calls without usage of a got trampoline }
procedure a_call_name_static(list : TAsmList;pd : tprocdef;const s : TSymStr);virtual; function a_call_name_static(list : TAsmList;pd : tprocdef;const s : TSymStr; forceresdef: tdef): tcgpara;virtual;
{ same as a_call_name, might be overridden on certain architectures to emit { same as a_call_name, might be overridden on certain architectures to emit
special static calls for inherited methods } special static calls for inherited methods }
procedure a_call_name_inherited(list : TAsmList;pd : tprocdef;const s : TSymStr);virtual; procedure a_call_name_inherited(list : TAsmList;pd : tprocdef;const s : TSymStr);virtual;
@ -533,7 +534,11 @@ unit hlcgobj;
procedure record_generated_code_for_procdef(pd: tprocdef; code, data: TAsmList); virtual; procedure record_generated_code_for_procdef(pd: tprocdef; code, data: TAsmList); virtual;
{ generate a call to a routine in the system unit } { generate a call to a routine in the system unit }
procedure g_call_system_proc(list: TAsmList; const procname: string); function g_call_system_proc(list: TAsmList; const procname: string; forceresdef: tdef): tcgpara;
protected
function g_call_system_proc_intern(list: TAsmList; pd: tprocdef; forceresdef: tdef): tcgpara; virtual;
public
{ Generate code to exit an unwind-protected region. The default implementation { Generate code to exit an unwind-protected region. The default implementation
produces a simple jump to destination label. } produces a simple jump to destination label. }
@ -868,6 +873,19 @@ implementation
end; end;
end; end;
function thlcgobj.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; forceresdef: tdef; weak: boolean): tcgpara;
begin
{ this is incomplete, it only sets the default function result location;
for use by descendants }
if not assigned(forceresdef) then
begin
pd.init_paraloc_info(callerside);
result:=pd.funcretloc[callerside];
end
else
result:=paramanager.get_funcretloc(pd,callerside,forceresdef);
end;
procedure thlcgobj.a_call_ref(list: TAsmList; pd: tabstractprocdef; const ref: treference); procedure thlcgobj.a_call_ref(list: TAsmList; pd: tabstractprocdef; const ref: treference);
var var
reg: tregister; reg: tregister;
@ -884,14 +902,14 @@ implementation
a_call_reg(list,pd,reg); a_call_reg(list,pd,reg);
end; end;
procedure thlcgobj.a_call_name_static(list: TAsmList; pd: tprocdef; const s: TSymStr); function thlcgobj.a_call_name_static(list: TAsmList; pd: tprocdef; const s: TSymStr; forceresdef: tdef): tcgpara;
begin begin
a_call_name(list,pd,s,false); result:=a_call_name(list,pd,s,forceresdef,false);
end; end;
procedure thlcgobj.a_call_name_inherited(list: TAsmList; pd: tprocdef; const s: TSymStr); procedure thlcgobj.a_call_name_inherited(list: TAsmList; pd: tprocdef; const s: TSymStr);
begin begin
a_call_name(list,pd,s,false); a_call_name(list,pd,s,nil,false);
end; end;
procedure thlcgobj.a_load_const_ref(list: TAsmList; tosize: tdef; a: aint; const ref: treference); procedure thlcgobj.a_load_const_ref(list: TAsmList; tosize: tdef; a: aint; const ref: treference);
@ -2770,7 +2788,7 @@ implementation
paramanager.getintparaloc(pocall_default,1,s32inttype,cgpara1); paramanager.getintparaloc(pocall_default,1,s32inttype,cgpara1);
a_load_const_cgpara(list,s32inttype,aint(210),cgpara1); a_load_const_cgpara(list,s32inttype,aint(210),cgpara1);
paramanager.freecgpara(list,cgpara1); paramanager.freecgpara(list,cgpara1);
g_call_system_proc(list,'fpc_handleerror'); g_call_system_proc(list,'fpc_handleerror',nil);
cgpara1.done; cgpara1.done;
a_label(list,oklabel); a_label(list,oklabel);
end; end;
@ -2810,7 +2828,7 @@ implementation
paramanager.freecgpara(list,cgpara3); paramanager.freecgpara(list,cgpara3);
paramanager.freecgpara(list,cgpara2); paramanager.freecgpara(list,cgpara2);
paramanager.freecgpara(list,cgpara1); paramanager.freecgpara(list,cgpara1);
g_call_system_proc(list,'fpc_shortstr_assign'); g_call_system_proc(list,'fpc_shortstr_assign',nil);
cgpara3.done; cgpara3.done;
cgpara2.done; cgpara2.done;
cgpara1.done; cgpara1.done;
@ -2830,7 +2848,7 @@ implementation
a_loadaddr_ref_cgpara(list,vardef,source,cgpara1); a_loadaddr_ref_cgpara(list,vardef,source,cgpara1);
paramanager.freecgpara(list,cgpara2); paramanager.freecgpara(list,cgpara2);
paramanager.freecgpara(list,cgpara1); paramanager.freecgpara(list,cgpara1);
g_call_system_proc(list,'fpc_variant_copy_overwrite'); g_call_system_proc(list,'fpc_variant_copy_overwrite',nil);
cgpara2.done; cgpara2.done;
cgpara1.done; cgpara1.done;
end; end;
@ -2868,7 +2886,7 @@ implementation
{ these functions get the pointer by value } { these functions get the pointer by value }
a_load_ref_cgpara(list,t,ref,cgpara1); a_load_ref_cgpara(list,t,ref,cgpara1);
paramanager.freecgpara(list,cgpara1); paramanager.freecgpara(list,cgpara1);
g_call_system_proc(list,incrfunc); g_call_system_proc(list,incrfunc,nil);
end end
else else
begin begin
@ -2879,7 +2897,7 @@ implementation
a_loadaddr_ref_cgpara(list,t,ref,cgpara1); a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
paramanager.freecgpara(list,cgpara1); paramanager.freecgpara(list,cgpara1);
paramanager.freecgpara(list,cgpara2); paramanager.freecgpara(list,cgpara2);
g_call_system_proc(list,'fpc_addref'); g_call_system_proc(list,'fpc_addref',nil);
end; end;
cgpara2.done; cgpara2.done;
cgpara1.done; cgpara1.done;
@ -2905,7 +2923,7 @@ implementation
paramanager.getintparaloc(pocall_default,1,pvardata,cgpara1); paramanager.getintparaloc(pocall_default,1,pvardata,cgpara1);
a_loadaddr_ref_cgpara(list,t,ref,cgpara1); a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
paramanager.freecgpara(list,cgpara1); paramanager.freecgpara(list,cgpara1);
g_call_system_proc(list,'fpc_variant_init'); g_call_system_proc(list,'fpc_variant_init',nil);
end end
else else
begin begin
@ -2918,7 +2936,7 @@ implementation
a_loadaddr_ref_cgpara(list,t,ref,cgpara1); a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
paramanager.freecgpara(list,cgpara1); paramanager.freecgpara(list,cgpara1);
paramanager.freecgpara(list,cgpara2); paramanager.freecgpara(list,cgpara2);
g_call_system_proc(list,'fpc_initialize'); g_call_system_proc(list,'fpc_initialize',nil);
end; end;
cgpara1.done; cgpara1.done;
cgpara2.done; cgpara2.done;
@ -2965,9 +2983,9 @@ implementation
paramanager.freecgpara(list,cgpara1); paramanager.freecgpara(list,cgpara1);
paramanager.freecgpara(list,cgpara2); paramanager.freecgpara(list,cgpara2);
if dynarr then if dynarr then
g_call_system_proc(list,'fpc_dynarray_clear') g_call_system_proc(list,'fpc_dynarray_clear',nil)
else else
g_call_system_proc(list,'fpc_finalize'); g_call_system_proc(list,'fpc_finalize',nil);
cgpara1.done; cgpara1.done;
cgpara2.done; cgpara2.done;
exit; exit;
@ -2976,7 +2994,7 @@ implementation
paramanager.getintparaloc(pocall_default,1,paratype,cgpara1); paramanager.getintparaloc(pocall_default,1,paratype,cgpara1);
a_loadaddr_ref_cgpara(list,t,ref,cgpara1); a_loadaddr_ref_cgpara(list,t,ref,cgpara1);
paramanager.freecgpara(list,cgpara1); paramanager.freecgpara(list,cgpara1);
g_call_system_proc(list,decrfunc); g_call_system_proc(list,decrfunc,nil);
cgpara1.done; cgpara1.done;
end; end;
@ -3016,7 +3034,7 @@ implementation
paramanager.freecgpara(list,cgpara1); paramanager.freecgpara(list,cgpara1);
paramanager.freecgpara(list,cgpara2); paramanager.freecgpara(list,cgpara2);
paramanager.freecgpara(list,cgpara3); paramanager.freecgpara(list,cgpara3);
g_call_system_proc(list,name); g_call_system_proc(list,name,nil);
cgpara3.done; cgpara3.done;
cgpara2.done; cgpara2.done;
@ -3187,7 +3205,7 @@ implementation
{ if low(to) > maxlongint also range error } { if low(to) > maxlongint also range error }
(lto > aintmax) then (lto > aintmax) then
begin begin
g_call_system_proc(list,'fpc_rangeerror'); g_call_system_proc(list,'fpc_rangeerror',nil);
exit exit
end; end;
{ from is signed and to is unsigned -> when looking at to } { from is signed and to is unsigned -> when looking at to }
@ -3202,7 +3220,7 @@ implementation
if (lfrom > aintmax) or if (lfrom > aintmax) or
(hto < 0) then (hto < 0) then
begin begin
g_call_system_proc(list,'fpc_rangeerror'); g_call_system_proc(list,'fpc_rangeerror',nil);
exit exit
end; end;
{ from is unsigned and to is signed -> when looking at to } { from is unsigned and to is signed -> when looking at to }
@ -3225,7 +3243,7 @@ implementation
a_cmp_const_reg_label(list,maxdef,OC_BE,aintmax,hreg,neglabel) a_cmp_const_reg_label(list,maxdef,OC_BE,aintmax,hreg,neglabel)
else else
a_cmp_const_reg_label(list,maxdef,OC_BE,tcgint(int64(hto-lto)),hreg,neglabel); a_cmp_const_reg_label(list,maxdef,OC_BE,tcgint(int64(hto-lto)),hreg,neglabel);
g_call_system_proc(list,'fpc_rangeerror'); g_call_system_proc(list,'fpc_rangeerror',nil);
a_label(list,neglabel); a_label(list,neglabel);
end; end;
@ -4319,7 +4337,7 @@ implementation
current_asmdata.asmlists[al_procedures].concatlist(data); current_asmdata.asmlists[al_procedures].concatlist(data);
end; end;
procedure thlcgobj.g_call_system_proc(list: TAsmList; const procname: string); function thlcgobj.g_call_system_proc(list: TAsmList; const procname: string; forceresdef: tdef): tcgpara;
var var
srsym: tsym; srsym: tsym;
pd: tprocdef; pd: tprocdef;
@ -4332,8 +4350,13 @@ implementation
(srsym.typ<>procsym) then (srsym.typ<>procsym) then
Message1(cg_f_unknown_compilerproc,procname); Message1(cg_f_unknown_compilerproc,procname);
pd:=tprocdef(tprocsym(srsym).procdeflist[0]); pd:=tprocdef(tprocsym(srsym).procdeflist[0]);
result:=g_call_system_proc_intern(list,pd,forceresdef);
end;
function thlcgobj.g_call_system_proc_intern(list: TAsmList; pd: tprocdef; forceresdef: tdef): tcgpara;
begin
allocallcpuregisters(list); allocallcpuregisters(list);
a_call_name(list,pd,pd.mangledname,false); result:=a_call_name(list,pd,pd.mangledname,forceresdef,false);
deallocallcpuregisters(list); deallocallcpuregisters(list);
end; end;

View File

@ -50,7 +50,7 @@ uses
procedure a_load_const_cgpara(list : TAsmList;tosize : tdef;a : aint;const cgpara : TCGPara);override; procedure a_load_const_cgpara(list : TAsmList;tosize : tdef;a : aint;const cgpara : TCGPara);override;
procedure a_call_name(list : TAsmList;pd : tprocdef;const s : TSymStr; weak: boolean);override; function a_call_name(list : TAsmList;pd : tprocdef;const s : TSymStr; forceresdef: tdef; weak: boolean): tcgpara;override;
procedure a_call_name_inherited(list : TAsmList;pd : tprocdef;const s : TSymStr);override; procedure a_call_name_inherited(list : TAsmList;pd : tprocdef;const s : TSymStr);override;
procedure a_call_reg(list: TAsmList; pd: tabstractprocdef; reg: tregister); override; procedure a_call_reg(list: TAsmList; pd: tabstractprocdef; reg: tregister); override;
@ -158,6 +158,10 @@ uses
then they have to be zero-extended again on the consumer side } then they have to be zero-extended again on the consumer side }
procedure maybe_resize_stack_para_val(list: TAsmList; retdef: tdef; callside: boolean); procedure maybe_resize_stack_para_val(list: TAsmList; retdef: tdef; callside: boolean);
{ adjust the stack height after a call based on the specified number of
slots used for parameters and the provided resultdef }
procedure g_adjust_stack_after_call(list: TAsmList; pd: tabstractprocdef; paraheight: longint; forceresdef: tdef);
property maxevalstackheight: longint read fmaxevalstackheight; property maxevalstackheight: longint read fmaxevalstackheight;
@ -178,6 +182,7 @@ uses
procedure inittempvariables(list:TAsmList);override; procedure inittempvariables(list:TAsmList);override;
function g_call_system_proc_intern(list: TAsmList; pd: tprocdef; forceresdef: tdef): tcgpara; override;
{ in case of an array, the array base address and index have to be { in case of an array, the array base address and index have to be
put on the evaluation stack before the stored value; similarly, for put on the evaluation stack before the stored value; similarly, for
@ -199,7 +204,7 @@ uses
JVM does not support unsigned divisions } JVM does not support unsigned divisions }
procedure maybepreparedivu32(list: TAsmList; var op: topcg; size: tdef; out isdivu32: boolean); procedure maybepreparedivu32(list: TAsmList; var op: topcg; size: tdef; out isdivu32: boolean);
{ common implementation of a_call_* } { common implementation of a_call_* }
procedure a_call_name_intern(list : TAsmList;pd : tprocdef;const s : TSymStr; inheritedcall: boolean); function a_call_name_intern(list : TAsmList;pd : tprocdef;const s : TSymStr; forceresdef: tdef; inheritedcall: boolean): tcgpara;
{ concatcopy helpers } { concatcopy helpers }
procedure concatcopy_normal_array(list: TAsmList; size: tdef; const source, dest: treference); procedure concatcopy_normal_array(list: TAsmList; size: tdef; const source, dest: treference);
@ -291,14 +296,14 @@ implementation
inherited a_load_const_cgpara(list, tosize, a, cgpara); inherited a_load_const_cgpara(list, tosize, a, cgpara);
end; end;
procedure thlcgjvm.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; weak: boolean); function thlcgjvm.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; forceresdef: tdef; weak: boolean): tcgpara;
begin begin
a_call_name_intern(list,pd,s,false); result:=a_call_name_intern(list,pd,s,forceresdef,false);
end; end;
procedure thlcgjvm.a_call_name_inherited(list: TAsmList; pd: tprocdef; const s: TSymStr); procedure thlcgjvm.a_call_name_inherited(list: TAsmList; pd: tprocdef; const s: TSymStr);
begin begin
a_call_name_intern(list,pd,s,true); a_call_name_intern(list,pd,s,nil,true);
end; end;
@ -632,7 +637,6 @@ implementation
i: longint; i: longint;
mangledname: string; mangledname: string;
opc: tasmop; opc: tasmop;
parasize: longint;
primitivetype: boolean; primitivetype: boolean;
begin begin
elemdef:=arrdef; elemdef:=arrdef;
@ -682,50 +686,46 @@ implementation
list.concat(taicpu.op_none(a_dup)); list.concat(taicpu.op_none(a_dup));
incstack(list,1); incstack(list,1);
a_load_const_stack(list,s32inttype,initdim-1,R_INTREGISTER); a_load_const_stack(list,s32inttype,initdim-1,R_INTREGISTER);
parasize:=2;
case elemdef.typ of case elemdef.typ of
arraydef: arraydef:
g_call_system_proc(list,'fpc_initialize_array_dynarr'); g_call_system_proc(list,'fpc_initialize_array_dynarr',nil);
recorddef,setdef,procvardef: recorddef,setdef,procvardef:
begin begin
tg.gethltemp(list,elemdef,elemdef.size,tt_persistent,recref); tg.gethltemp(list,elemdef,elemdef.size,tt_persistent,recref);
a_load_ref_stack(list,elemdef,recref,prepare_stack_for_ref(list,recref,false)); a_load_ref_stack(list,elemdef,recref,prepare_stack_for_ref(list,recref,false));
inc(parasize);
case elemdef.typ of case elemdef.typ of
recorddef: recorddef:
g_call_system_proc(list,'fpc_initialize_array_record'); g_call_system_proc(list,'fpc_initialize_array_record',nil);
setdef: setdef:
begin begin
if tsetdef(elemdef).elementdef.typ=enumdef then if tsetdef(elemdef).elementdef.typ=enumdef then
g_call_system_proc(list,'fpc_initialize_array_enumset') g_call_system_proc(list,'fpc_initialize_array_enumset',nil)
else else
g_call_system_proc(list,'fpc_initialize_array_bitset') g_call_system_proc(list,'fpc_initialize_array_bitset',nil)
end; end;
procvardef: procvardef:
g_call_system_proc(list,'fpc_initialize_array_procvar'); g_call_system_proc(list,'fpc_initialize_array_procvar',nil);
end; end;
tg.ungettemp(list,recref); tg.ungettemp(list,recref);
end; end;
enumdef: enumdef:
begin begin
inc(parasize);
a_load_ref_stack(list,java_jlobject,enuminitref,prepare_stack_for_ref(list,enuminitref,false)); a_load_ref_stack(list,java_jlobject,enuminitref,prepare_stack_for_ref(list,enuminitref,false));
g_call_system_proc(list,'fpc_initialize_array_object'); g_call_system_proc(list,'fpc_initialize_array_object',nil);
end; end;
stringdef: stringdef:
begin begin
case tstringdef(elemdef).stringtype of case tstringdef(elemdef).stringtype of
st_shortstring: st_shortstring:
begin begin
inc(parasize);
a_load_const_stack_intern(list,u8inttype,tstringdef(elemdef).len,R_INTREGISTER,true); a_load_const_stack_intern(list,u8inttype,tstringdef(elemdef).len,R_INTREGISTER,true);
g_call_system_proc(list,'fpc_initialize_array_shortstring'); g_call_system_proc(list,'fpc_initialize_array_shortstring',nil);
end; end;
st_ansistring: st_ansistring:
g_call_system_proc(list,'fpc_initialize_array_ansistring'); g_call_system_proc(list,'fpc_initialize_array_ansistring',nil);
st_unicodestring, st_unicodestring,
st_widestring: st_widestring:
g_call_system_proc(list,'fpc_initialize_array_unicodestring'); g_call_system_proc(list,'fpc_initialize_array_unicodestring',nil);
else else
internalerror(2011081801); internalerror(2011081801);
end; end;
@ -733,7 +733,6 @@ implementation
else else
internalerror(2011081801); internalerror(2011081801);
end; end;
decstack(list,parasize);
end; end;
end; end;
@ -933,6 +932,15 @@ implementation
{ these are automatically initialised when allocated if necessary } { these are automatically initialised when allocated if necessary }
end; end;
function thlcgjvm.g_call_system_proc_intern(list: TAsmList; pd: tprocdef; forceresdef: tdef): tcgpara;
begin
result:=inherited;
pd.init_paraloc_info(callerside);
g_adjust_stack_after_call(list,pd,pd.callerargareasize,forceresdef);
end;
function thlcgjvm.prepare_stack_for_ref(list: TAsmList; const ref: treference; dup: boolean): longint; function thlcgjvm.prepare_stack_for_ref(list: TAsmList; const ref: treference; dup: boolean): longint;
var var
href: treference; href: treference;
@ -1287,16 +1295,9 @@ implementation
a_load_const_stack(list,s32inttype,-1,R_INTREGISTER); a_load_const_stack(list,s32inttype,-1,R_INTREGISTER);
a_load_const_stack(list,s32inttype,-1,R_INTREGISTER); a_load_const_stack(list,s32inttype,-1,R_INTREGISTER);
end; end;
g_call_system_proc(list,procname); g_call_system_proc(list,procname,nil);
if ndim=1 then if ndim<>1 then
begin begin
decstack(list,2);
if adddefaultlenparas then
decstack(list,2);
end
else
begin
decstack(list,4);
{ pop return value, must be the same as dest } { pop return value, must be the same as dest }
list.concat(taicpu.op_none(a_pop)); list.concat(taicpu.op_none(a_pop));
decstack(list,1); decstack(list,1);
@ -1318,7 +1319,7 @@ implementation
(srsym.typ<>procsym) then (srsym.typ<>procsym) then
Message1(cg_f_unknown_compilerproc,size.typename+'.fpcDeepCopy'); Message1(cg_f_unknown_compilerproc,size.typename+'.fpcDeepCopy');
pd:=tprocdef(tprocsym(srsym).procdeflist[0]); pd:=tprocdef(tprocsym(srsym).procdeflist[0]);
a_call_name(list,pd,pd.mangledname,false); a_call_name(list,pd,pd.mangledname,nil,false);
{ both parameters are removed, no function result } { both parameters are removed, no function result }
decstack(list,2); decstack(list,2);
end; end;
@ -1330,11 +1331,9 @@ implementation
a_load_ref_stack(list,size,dest,prepare_stack_for_ref(list,dest,false)); a_load_ref_stack(list,size,dest,prepare_stack_for_ref(list,dest,false));
{ call set copy helper } { call set copy helper }
if tsetdef(size).elementdef.typ=enumdef then if tsetdef(size).elementdef.typ=enumdef then
g_call_system_proc(list,'fpc_enumset_copy') g_call_system_proc(list,'fpc_enumset_copy',nil)
else else
g_call_system_proc(list,'fpc_bitset_copy'); g_call_system_proc(list,'fpc_bitset_copy',nil);
{ both parameters are removed, no function result }
decstack(list,2);
end; end;
@ -1353,7 +1352,7 @@ implementation
(srsym.typ<>procsym) then (srsym.typ<>procsym) then
Message1(cg_f_unknown_compilerproc,'ShortstringClass.FpcDeepCopy'); Message1(cg_f_unknown_compilerproc,'ShortstringClass.FpcDeepCopy');
pd:=tprocdef(tprocsym(srsym).procdeflist[0]); pd:=tprocdef(tprocsym(srsym).procdeflist[0]);
a_call_name(list,pd,pd.mangledname,false); a_call_name(list,pd,pd.mangledname,nil,false);
{ both parameters are removed, no function result } { both parameters are removed, no function result }
decstack(list,2); decstack(list,2);
end; end;
@ -1543,22 +1542,22 @@ implementation
a_load_const_stack(list,s32inttype,normaldim,R_INTREGISTER); a_load_const_stack(list,s32inttype,normaldim,R_INTREGISTER);
{ highloc is invalid, the length is part of the array in Java } { highloc is invalid, the length is part of the array in Java }
if is_wide_or_unicode_string(t) then if is_wide_or_unicode_string(t) then
g_call_system_proc(list,'fpc_initialize_array_unicodestring') g_call_system_proc(list,'fpc_initialize_array_unicodestring',nil)
else if is_ansistring(t) then else if is_ansistring(t) then
g_call_system_proc(list,'fpc_initialize_array_ansistring') g_call_system_proc(list,'fpc_initialize_array_ansistring',nil)
else if is_dynamic_array(t) then else if is_dynamic_array(t) then
g_call_system_proc(list,'fpc_initialize_array_dynarr') g_call_system_proc(list,'fpc_initialize_array_dynarr',nil)
else if is_record(t) or else if is_record(t) or
(t.typ=setdef) then (t.typ=setdef) then
begin begin
tg.gethltemp(list,t,t.size,tt_persistent,eleref); tg.gethltemp(list,t,t.size,tt_persistent,eleref);
a_load_ref_stack(list,t,eleref,prepare_stack_for_ref(list,eleref,false)); a_load_ref_stack(list,t,eleref,prepare_stack_for_ref(list,eleref,false));
if is_record(t) then if is_record(t) then
g_call_system_proc(list,'fpc_initialize_array_record') g_call_system_proc(list,'fpc_initialize_array_record',nil)
else if tsetdef(t).elementdef.typ=enumdef then else if tsetdef(t).elementdef.typ=enumdef then
g_call_system_proc(list,'fpc_initialize_array_enumset') g_call_system_proc(list,'fpc_initialize_array_enumset',nil)
else else
g_call_system_proc(list,'fpc_initialize_array_bitset'); g_call_system_proc(list,'fpc_initialize_array_bitset',nil);
tg.ungettemp(list,eleref); tg.ungettemp(list,eleref);
end end
else if (t.typ=enumdef) then else if (t.typ=enumdef) then
@ -1566,7 +1565,7 @@ implementation
if get_enum_init_val_ref(t,eleref) then if get_enum_init_val_ref(t,eleref) then
begin begin
a_load_ref_stack(list,java_jlobject,eleref,prepare_stack_for_ref(list,eleref,false)); a_load_ref_stack(list,java_jlobject,eleref,prepare_stack_for_ref(list,eleref,false));
g_call_system_proc(list,'fpc_initialize_array_object'); g_call_system_proc(list,'fpc_initialize_array_object',nil);
end; end;
end end
else else
@ -1597,7 +1596,7 @@ implementation
pd:=tprocdef(tprocsym(sym).procdeflist[0]); pd:=tprocdef(tprocsym(sym).procdeflist[0]);
end; end;
a_load_ref_stack(list,java_jlobject,ref,prepare_stack_for_ref(list,ref,false)); a_load_ref_stack(list,java_jlobject,ref,prepare_stack_for_ref(list,ref,false));
a_call_name(list,pd,pd.mangledname,false); a_call_name(list,pd,pd.mangledname,nil,false);
{ parameter removed, no result } { parameter removed, no result }
decstack(list,1); decstack(list,1);
end end
@ -2060,6 +2059,31 @@ implementation
end; end;
end; end;
procedure thlcgjvm.g_adjust_stack_after_call(list: TAsmList; pd: tabstractprocdef; paraheight: longint; forceresdef: tdef);
var
totalremovesize: longint;
realresdef: tdef;
begin
if not assigned(forceresdef) then
realresdef:=pd.returndef
else
realresdef:=forceresdef;
{ a constructor doesn't actually return a value in the jvm }
if (tabstractprocdef(pd).proctypeoption=potype_constructor) then
totalremovesize:=paraheight
else
{ even a byte takes up a full stackslot -> align size to multiple of 4 }
totalremovesize:=paraheight-(align(realresdef.size,4) shr 2);
{ remove parameters from internal evaluation stack counter (in case of
e.g. no parameters and a result, it can also increase) }
if totalremovesize>0 then
decstack(list,totalremovesize)
else if totalremovesize<0 then
incstack(list,-totalremovesize);
end;
procedure thlcgjvm.allocate_implicit_struct_with_base_ref(list: TAsmList; vs: tabstractvarsym; ref: treference); procedure thlcgjvm.allocate_implicit_struct_with_base_ref(list: TAsmList; vs: tabstractvarsym; ref: treference);
var var
tmpref: treference; tmpref: treference;
@ -2256,7 +2280,7 @@ implementation
isdivu32:=false; isdivu32:=false;
end; end;
procedure thlcgjvm.a_call_name_intern(list: TAsmList; pd: tprocdef; const s: TSymStr; inheritedcall: boolean); function thlcgjvm.a_call_name_intern(list: TAsmList; pd: tprocdef; const s: TSymStr; forceresdef: tdef; inheritedcall: boolean): tcgpara;
var var
opc: tasmop; opc: tasmop;
begin begin
@ -2319,6 +2343,7 @@ implementation
pd.init_paraloc_info(calleeside); pd.init_paraloc_info(calleeside);
list.concat(taicpu.op_sym_const(opc,current_asmdata.RefAsmSymbol(s),pd.calleeargareasize)); list.concat(taicpu.op_sym_const(opc,current_asmdata.RefAsmSymbol(s),pd.calleeargareasize));
end; end;
result:=inherited a_call_name(list,pd,s,forceresdef,false);
end; end;
procedure create_hlcodegen; procedure create_hlcodegen;

View File

@ -439,33 +439,21 @@ implementation
procedure tjvmcallnode.extra_post_call_code; procedure tjvmcallnode.extra_post_call_code;
var var
totalremovesize: longint;
realresdef: tdef; realresdef: tdef;
begin
thlcgjvm(hlcg).g_adjust_stack_after_call(current_asmdata.CurrAsmList,procdefinition,pushedparasize,typedef);
{ a constructor doesn't actually return a value in the jvm }
if (tabstractprocdef(procdefinition).proctypeoption<>potype_constructor) then
begin
if cnf_return_value_used in callnodeflags then
begin begin
if not assigned(typedef) then if not assigned(typedef) then
realresdef:=tstoreddef(resultdef) realresdef:=tstoreddef(resultdef)
else else
realresdef:=tstoreddef(typedef); realresdef:=tstoreddef(typedef);
{ a constructor doesn't actually return a value in the jvm }
if (tabstractprocdef(procdefinition).proctypeoption=potype_constructor) then
totalremovesize:=pushedparasize
else
begin
{ zero-extend unsigned 8/16 bit returns (we have to return them
sign-extended to keep the Android verifier happy, and even if that
one did not exist a plain Java routine could return a
sign-extended value) }
if cnf_return_value_used in callnodeflags then
thlcgjvm(hlcg).maybe_resize_stack_para_val(current_asmdata.CurrAsmList,realresdef,false); thlcgjvm(hlcg).maybe_resize_stack_para_val(current_asmdata.CurrAsmList,realresdef,false);
{ even a byte takes up a full stackslot -> align size to multiple of 4 }
totalremovesize:=pushedparasize-(align(realresdef.size,4) shr 2);
end; end;
{ remove parameters from internal evaluation stack counter (in case of end;
e.g. no parameters and a result, it can also increase) }
if totalremovesize>0 then
thlcgjvm(hlcg).decstack(current_asmdata.CurrAsmList,totalremovesize)
else if totalremovesize<0 then
thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,-totalremovesize);
{ if this was an inherited constructor call, initialise all fields that { if this was an inherited constructor call, initialise all fields that
are wrapped types following it } are wrapped types following it }

View File

@ -415,7 +415,7 @@ implementation
(tprocsym(psym).ProcdefList.count<>1) then (tprocsym(psym).ProcdefList.count<>1) then
internalerror(2011062607); internalerror(2011062607);
thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,right.resultdef,right.location); thlcgjvm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,right.resultdef,right.location);
hlcg.a_call_name(current_asmdata.CurrAsmList,tprocdef(tprocsym(psym).procdeflist[0]),tprocdef(tprocsym(psym).procdeflist[0]).mangledname,false); hlcg.a_call_name(current_asmdata.CurrAsmList,tprocdef(tprocsym(psym).procdeflist[0]),tprocdef(tprocsym(psym).procdeflist[0]).mangledname,nil,false);
{ call replaces self parameter with longint result -> no stack { call replaces self parameter with longint result -> no stack
height change } height change }
location_reset(right.location,LOC_REGISTER,OS_S32); location_reset(right.location,LOC_REGISTER,OS_S32);

View File

@ -85,7 +85,7 @@ unit tgcpu;
end end
else else
internalerror(2011060301); internalerror(2011060301);
hlcg.a_call_name(list,pd,pd.mangledname,false); hlcg.a_call_name(list,pd,pd.mangledname,nil,false);
thlcgjvm(hlcg).decstack(list,1); thlcgjvm(hlcg).decstack(list,1);
{ store reference to instance } { store reference to instance }
thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0); thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0);
@ -146,7 +146,7 @@ unit tgcpu;
internalerror(2011062801); internalerror(2011062801);
pd:=tprocdef(tprocsym(sym).procdeflist[0]); pd:=tprocdef(tprocsym(sym).procdeflist[0]);
end; end;
hlcg.a_call_name(list,pd,pd.mangledname,false); hlcg.a_call_name(list,pd,pd.mangledname,nil,false);
{ static calls method replaces parameter with set instance { static calls method replaces parameter with set instance
-> no change in stack height } -> no change in stack height }
end end
@ -169,7 +169,7 @@ unit tgcpu;
end end
else else
internalerror(2011062803); internalerror(2011062803);
hlcg.a_call_name(list,pd,pd.mangledname,false); hlcg.a_call_name(list,pd,pd.mangledname,nil,false);
{ duplicate self pointer is removed } { duplicate self pointer is removed }
thlcgjvm(hlcg).decstack(list,1); thlcgjvm(hlcg).decstack(list,1);
end; end;
@ -203,7 +203,7 @@ unit tgcpu;
internalerror(2011052404); internalerror(2011052404);
pd:=tprocdef(tprocsym(sym).procdeflist[0]); pd:=tprocdef(tprocsym(sym).procdeflist[0]);
end; end;
hlcg.a_call_name(list,pd,pd.mangledname,false); hlcg.a_call_name(list,pd,pd.mangledname,nil,false);
{ static calls method replaces parameter with string instance { static calls method replaces parameter with string instance
-> no change in stack height } -> no change in stack height }
{ store reference to instance } { store reference to instance }

View File

@ -32,12 +32,12 @@ uses
globtype, globtype,
aasmbase, aasmdata, aasmbase, aasmdata,
cgbase, cgutils, cgbase, cgutils,
symdef, symtype,symdef,
hlcgobj, hlcg2ll; parabase, hlcgobj, hlcg2ll;
type type
thlcg2mips = class(thlcg2ll) thlcgmips = class(thlcg2ll)
procedure a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; weak: boolean);override; function a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; forceresdef: tdef; weak: boolean): tcgpara; override;
procedure a_call_reg(list : TAsmList;pd : tabstractprocdef;reg : tregister);override; procedure a_call_reg(list : TAsmList;pd : tabstractprocdef;reg : tregister);override;
procedure a_call_ref(list : TAsmList;pd : tabstractprocdef;const ref : treference);override; procedure a_call_ref(list : TAsmList;pd : tabstractprocdef;const ref : treference);override;
end; end;
@ -53,7 +53,7 @@ implementation
cpubase, cpubase,
cgcpu; cgcpu;
procedure thlcg2mips.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; weak: boolean); function thlcgmips.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; forceresdef: tdef; weak: boolean): tcgpara;
var var
ref : treference; ref : treference;
begin begin
@ -73,9 +73,11 @@ implementation
end end
else else
cg.a_call_name(list,s,weak); cg.a_call_name(list,s,weak);
{ the default implementation only determines the result location }
result:=inherited;
end; end;
procedure thlcg2mips.a_call_reg(list: TAsmList; pd: tabstractprocdef; reg: tregister); procedure thlcgmips.a_call_reg(list: TAsmList; pd: tabstractprocdef; reg: tregister);
begin begin
if (pd.proccalloption=pocall_cdecl) and (reg<>NR_PIC_FUNC) then if (pd.proccalloption=pocall_cdecl) and (reg<>NR_PIC_FUNC) then
begin begin
@ -88,7 +90,7 @@ implementation
cg.a_call_reg(list,reg); cg.a_call_reg(list,reg);
end; end;
procedure thlcg2mips.a_call_ref(list: TAsmList; pd: tabstractprocdef; const ref: treference); procedure thlcgmips.a_call_ref(list: TAsmList; pd: tabstractprocdef; const ref: treference);
begin begin
if pd.proccalloption =pocall_cdecl then if pd.proccalloption =pocall_cdecl then
begin begin
@ -103,7 +105,7 @@ implementation
procedure create_hlcodegen; procedure create_hlcodegen;
begin begin
hlcg:=thlcg2mips.create; hlcg:=thlcgmips.create;
create_codegen; create_codegen;
end; end;

View File

@ -872,9 +872,9 @@ implementation
if cnf_inherited in callnodeflags then if cnf_inherited in callnodeflags then
hlcg.a_call_name_inherited(current_asmdata.CurrAsmList,tprocdef(procdefinition),tprocdef(procdefinition).mangledname) hlcg.a_call_name_inherited(current_asmdata.CurrAsmList,tprocdef(procdefinition),tprocdef(procdefinition).mangledname)
else else
hlcg.a_call_name(current_asmdata.CurrAsmList,tprocdef(procdefinition),tprocdef(procdefinition).mangledname,po_weakexternal in procdefinition.procoptions) hlcg.a_call_name(current_asmdata.CurrAsmList,tprocdef(procdefinition),tprocdef(procdefinition).mangledname,typedef,po_weakexternal in procdefinition.procoptions)
else else
hlcg.a_call_name(current_asmdata.CurrAsmList,tprocdef(procdefinition),name_to_call,po_weakexternal in procdefinition.procoptions); hlcg.a_call_name(current_asmdata.CurrAsmList,tprocdef(procdefinition),name_to_call,typedef,po_weakexternal in procdefinition.procoptions);
extra_post_call_code; extra_post_call_code;
end; end;
end; end;