mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 19:09:27 +02:00
+ hlcg implementation of gen_load_para_value(); no support yet for copying
value parameters when necessary, nor for -gt variable trashing git-svn-id: branches/jvmbackend@18367 -
This commit is contained in:
parent
2a6caa539c
commit
09207563d5
@ -394,6 +394,8 @@ unit hlcg2ll;
|
|||||||
|
|
||||||
procedure maketojumpbool(list:TAsmList; p : tnode);override;
|
procedure maketojumpbool(list:TAsmList; p : tnode);override;
|
||||||
|
|
||||||
|
procedure gen_load_para_value(list:TAsmList);override;
|
||||||
|
|
||||||
procedure gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara); override;
|
procedure gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara); override;
|
||||||
procedure gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean); override;
|
procedure gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean); override;
|
||||||
end;
|
end;
|
||||||
@ -1163,6 +1165,11 @@ procedure thlcg2ll.a_loadaddr_ref_reg(list: TAsmList; fromsize, tosize: tdef; co
|
|||||||
ncgutil.maketojumpbool(list,p,lr_dont_load_regvars);
|
ncgutil.maketojumpbool(list,p,lr_dont_load_regvars);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure thlcg2ll.gen_load_para_value(list: TAsmList);
|
||||||
|
begin
|
||||||
|
ncgutil.gen_load_para_value(list);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure thlcg2ll.gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara);
|
procedure thlcg2ll.gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara);
|
||||||
begin
|
begin
|
||||||
ncgutil.gen_load_loc_cgpara(list,vardef,l,cgpara);
|
ncgutil.gen_load_loc_cgpara(list,vardef,l,cgpara);
|
||||||
|
@ -426,6 +426,8 @@ unit hlcgobj;
|
|||||||
procedure gen_proc_symbol(list:TAsmList);virtual;
|
procedure gen_proc_symbol(list:TAsmList);virtual;
|
||||||
procedure gen_proc_symbol_end(list:TAsmList);virtual;
|
procedure gen_proc_symbol_end(list:TAsmList);virtual;
|
||||||
|
|
||||||
|
procedure gen_load_para_value(list:TAsmList);virtual;
|
||||||
|
|
||||||
private
|
private
|
||||||
procedure gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation;const cgpara: tcgpara;locintsize: longint);virtual;
|
procedure gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation;const cgpara: tcgpara;locintsize: longint);virtual;
|
||||||
protected
|
protected
|
||||||
@ -1825,6 +1827,131 @@ implementation
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ generates the code for incrementing the reference count of parameters and
|
||||||
|
initialize out parameters }
|
||||||
|
procedure init_paras(p:TObject;arg:pointer);
|
||||||
|
var
|
||||||
|
href : treference;
|
||||||
|
tmpreg : tregister;
|
||||||
|
list : TAsmList;
|
||||||
|
needs_inittable (*,
|
||||||
|
do_trashing *) : boolean;
|
||||||
|
begin
|
||||||
|
list:=TAsmList(arg);
|
||||||
|
if (tsym(p).typ=paravarsym) then
|
||||||
|
begin
|
||||||
|
needs_inittable:=is_managed_type(tparavarsym(p).vardef);
|
||||||
|
(*
|
||||||
|
do_trashing:=
|
||||||
|
(localvartrashing <> -1) and
|
||||||
|
(not assigned(tparavarsym(p).defaultconstsym)) and
|
||||||
|
not needs_inittable;
|
||||||
|
*)
|
||||||
|
case tparavarsym(p).varspez of
|
||||||
|
vs_value :
|
||||||
|
if needs_inittable then
|
||||||
|
begin
|
||||||
|
{ variants are already handled by the call to fpc_variant_copy_overwrite if
|
||||||
|
they are passed by reference }
|
||||||
|
if not((tparavarsym(p).vardef.typ=variantdef) and
|
||||||
|
paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
|
||||||
|
begin
|
||||||
|
location_get_data_ref(list,tparavarsym(p).initialloc,href,is_open_array(tparavarsym(p).vardef),sizeof(pint));
|
||||||
|
hlcg.g_incrrefcount(list,tparavarsym(p).vardef,href);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
vs_out :
|
||||||
|
begin
|
||||||
|
if needs_inittable (*or
|
||||||
|
do_trashing*) then
|
||||||
|
begin
|
||||||
|
tmpreg:=cg.getaddressregister(list);
|
||||||
|
hlcg.a_load_loc_reg(list,tparavarsym(p).vardef,tparavarsym(p).vardef,tparavarsym(p).initialloc,tmpreg);
|
||||||
|
{ we have no idea about the alignment at the callee side,
|
||||||
|
and the user also cannot specify "unaligned" here, so
|
||||||
|
assume worst case }
|
||||||
|
reference_reset_base(href,tmpreg,0,1);
|
||||||
|
(*
|
||||||
|
if do_trashing and
|
||||||
|
{ needs separate implementation to trash open arrays }
|
||||||
|
{ since their size is only known at run time }
|
||||||
|
not is_special_array(tparavarsym(p).vardef) then
|
||||||
|
{ may be an open string, even if is_open_string() returns }
|
||||||
|
{ false (for some helpers in the system unit) }
|
||||||
|
if not is_shortstring(tparavarsym(p).vardef) then
|
||||||
|
trash_reference(list,href,tparavarsym(p).vardef.size)
|
||||||
|
else
|
||||||
|
trash_reference(list,href,2);
|
||||||
|
*)
|
||||||
|
if needs_inittable then
|
||||||
|
hlcg.g_initialize(list,tparavarsym(p).vardef,href);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
(*
|
||||||
|
else if do_trashing and
|
||||||
|
([vo_is_funcret,vo_is_hidden_para] * tparavarsym(p).varoptions = [vo_is_funcret,vo_is_hidden_para]) then
|
||||||
|
begin
|
||||||
|
tmpreg:=cg.getaddressregister(list);
|
||||||
|
a_load_loc_reg(list,tparavarsym(p).vardef,tparavarsym(p).vardef,tparavarsym(p).initialloc,tmpreg);
|
||||||
|
{ should always have standard alignment. If a function is assigned
|
||||||
|
to a non-aligned variable, the optimisation to pass this variable
|
||||||
|
directly as hidden function result must/cannot be performed
|
||||||
|
(see tcallnode.funcret_can_be_reused)
|
||||||
|
}
|
||||||
|
reference_reset_base(href,tmpreg,0,
|
||||||
|
used_align(tparavarsym(p).vardef.alignment,current_settings.alignment.localalignmin,current_settings.alignment.localalignmax));
|
||||||
|
{ may be an open string, even if is_open_string() returns }
|
||||||
|
{ false (for some helpers in the system unit) }
|
||||||
|
if not is_shortstring(tparavarsym(p).vardef) then
|
||||||
|
trash_reference(list,href,tparavarsym(p).vardef.size)
|
||||||
|
else
|
||||||
|
{ an open string has at least size 2 }
|
||||||
|
trash_reference(list,href,2);
|
||||||
|
end
|
||||||
|
*)
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure thlcgobj.gen_load_para_value(list: TAsmList);
|
||||||
|
var
|
||||||
|
i: longint;
|
||||||
|
currpara: tparavarsym;
|
||||||
|
begin
|
||||||
|
if (po_assembler in current_procinfo.procdef.procoptions) then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
{ Copy parameters to local references/registers }
|
||||||
|
for i:=0 to current_procinfo.procdef.paras.count-1 do
|
||||||
|
begin
|
||||||
|
currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
|
||||||
|
gen_load_cgpara_loc(list,currpara.vardef,currpara.paraloc[calleeside],currpara.initialloc,paramanager.param_use_paraloc(currpara.paraloc[calleeside]));
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ generate copies of call by value parameters, must be done before
|
||||||
|
the initialization and body is parsed because the refcounts are
|
||||||
|
incremented using the local copies }
|
||||||
|
// current_procinfo.procdef.parast.SymList.ForEachCall(@copyvalueparas,list);
|
||||||
|
|
||||||
|
if not(po_assembler in current_procinfo.procdef.procoptions) then
|
||||||
|
begin
|
||||||
|
{ has to be done here rather than in gen_initialize_code, because
|
||||||
|
the initialisation code is generated a) later and b) with
|
||||||
|
rad_backwards, so the register allocator would generate
|
||||||
|
information as if this code comes before loading the parameters
|
||||||
|
from their original registers to their local location }
|
||||||
|
// if (localvartrashing <> -1) then
|
||||||
|
// current_procinfo.procdef.localst.SymList.ForEachCall(@trash_variable,list);
|
||||||
|
{ initialize refcounted paras, and trash others. Needed here
|
||||||
|
instead of in gen_initialize_code, because when a reference is
|
||||||
|
intialised or trashed while the pointer to that reference is kept
|
||||||
|
in a regvar, we add a register move and that one again has to
|
||||||
|
come after the parameter loading code as far as the register
|
||||||
|
allocator is concerned }
|
||||||
|
current_procinfo.procdef.parast.SymList.ForEachCall(@init_paras,list);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure thlcgobj.gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation; const cgpara: tcgpara; locintsize: longint);
|
procedure thlcgobj.gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation; const cgpara: tcgpara; locintsize: longint);
|
||||||
begin
|
begin
|
||||||
case l.loc of
|
case l.loc of
|
||||||
|
@ -1049,7 +1049,7 @@ implementation
|
|||||||
{$endif oldreg}
|
{$endif oldreg}
|
||||||
current_filepos:=entrypos;
|
current_filepos:=entrypos;
|
||||||
|
|
||||||
gen_load_para_value(templist);
|
hlcg.gen_load_para_value(templist);
|
||||||
|
|
||||||
{ caller paraloc info is also necessary in the stackframe_entry
|
{ caller paraloc info is also necessary in the stackframe_entry
|
||||||
code of the ppc (and possibly other processors) }
|
code of the ppc (and possibly other processors) }
|
||||||
|
Loading…
Reference in New Issue
Block a user