mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-11-01 05:59:37 +01:00
* moved use_fixed_stack from cgutils to a method in paramgr so it can
be used outside the code generator
* renamed tabstractprocdef.requiredargarea into callerargareasize,
and also added calleeargareasize field; added init_paraloc_info(side)
method to init the parameter locations and init those size fields and
replaced all "if not procdef.has_paraloc_info then ..." blocks with
procdef.init_paraloc_info(callersize)"
* moved detection of stack tainting parameters from psub to
symdef/tabstractprocdef
+ added tcallparanode.contains_stack_tainting_call(), which detects
whether a parameter contains a call that makes use of stack paramters
* record for each parameter whether or not any following parameter
contains a call with stack parameters; if not, in case the current
parameter itself is a stack parameter immediately place it in its
final location also for use_fixed_stack platforms rather than
first putting it in a temporary location (part of mantis #17442)
* on use_fixed_stack platforms, always first evaluate parameters
containing a stack tainting call, since those force any preceding
stack parameters of the current call to be stored in a temp location
and copied to the final location afterwards
git-svn-id: trunk@16050 -
This commit is contained in:
parent
27948a5f06
commit
f13f6627c4
@ -2140,11 +2140,7 @@ unit cgcpu;
|
|||||||
shift : byte;
|
shift : byte;
|
||||||
begin
|
begin
|
||||||
{ calculate the parameter info for the procdef }
|
{ calculate the parameter info for the procdef }
|
||||||
if not procdef.has_paraloc_info then
|
procdef.init_paraloc_info(callerside);
|
||||||
begin
|
|
||||||
procdef.requiredargarea:=paramanager.create_paraloc_info(procdef,callerside);
|
|
||||||
procdef.has_paraloc_info:=true;
|
|
||||||
end;
|
|
||||||
hsym:=tsym(procdef.parast.Find('self'));
|
hsym:=tsym(procdef.parast.Find('self'));
|
||||||
if not(assigned(hsym) and
|
if not(assigned(hsym) and
|
||||||
(hsym.typ=paravarsym)) then
|
(hsym.typ=paravarsym)) then
|
||||||
|
|||||||
@ -4124,11 +4124,7 @@ implementation
|
|||||||
paraloc : Pcgparalocation;
|
paraloc : Pcgparalocation;
|
||||||
begin
|
begin
|
||||||
{ calculate the parameter info for the procdef }
|
{ calculate the parameter info for the procdef }
|
||||||
if not procdef.has_paraloc_info then
|
procdef.init_paraloc_info(callerside);
|
||||||
begin
|
|
||||||
procdef.requiredargarea:=paramanager.create_paraloc_info(procdef,callerside);
|
|
||||||
procdef.has_paraloc_info:=true;
|
|
||||||
end;
|
|
||||||
hsym:=tsym(procdef.parast.Find('self'));
|
hsym:=tsym(procdef.parast.Find('self'));
|
||||||
if not(assigned(hsym) and
|
if not(assigned(hsym) and
|
||||||
(hsym.typ=paravarsym)) then
|
(hsym.typ=paravarsym)) then
|
||||||
|
|||||||
@ -148,10 +148,6 @@ unit cgutils;
|
|||||||
procedure location_copy(var destloc:tlocation; const sourceloc : tlocation);
|
procedure location_copy(var destloc:tlocation; const sourceloc : tlocation);
|
||||||
procedure location_swap(var destloc,sourceloc : tlocation);
|
procedure location_swap(var destloc,sourceloc : tlocation);
|
||||||
|
|
||||||
|
|
||||||
{ allocate room for parameters on the stack in the entry code? }
|
|
||||||
function use_fixed_stack: boolean;
|
|
||||||
|
|
||||||
{ returns r with the given alignment }
|
{ returns r with the given alignment }
|
||||||
function setalignment(const r : treference;b : byte) : treference;
|
function setalignment(const r : treference;b : byte) : treference;
|
||||||
|
|
||||||
@ -248,18 +244,5 @@ uses
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
function use_fixed_stack: boolean;
|
|
||||||
begin
|
|
||||||
{$ifdef i386}
|
|
||||||
result := (target_info.system in [system_i386_darwin,system_x86_64_darwin]);
|
|
||||||
{$else i386}
|
|
||||||
{$ifdef cputargethasfixedstack}
|
|
||||||
result := true;
|
|
||||||
{$else cputargethasfixedstack}
|
|
||||||
result := false;
|
|
||||||
{$endif cputargethasfixedstack}
|
|
||||||
{$endif i386}
|
|
||||||
end;
|
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|||||||
@ -75,7 +75,7 @@ unit cgcpu;
|
|||||||
|
|
||||||
function use_push(const cgpara:tcgpara):boolean;
|
function use_push(const cgpara:tcgpara):boolean;
|
||||||
begin
|
begin
|
||||||
result:=(not use_fixed_stack) and
|
result:=(not paramanager.use_fixed_stack) and
|
||||||
assigned(cgpara.location) and
|
assigned(cgpara.location) and
|
||||||
(cgpara.location^.loc=LOC_REFERENCE) and
|
(cgpara.location^.loc=LOC_REFERENCE) and
|
||||||
(cgpara.location^.reference.index=NR_STACK_POINTER_REG);
|
(cgpara.location^.reference.index=NR_STACK_POINTER_REG);
|
||||||
@ -325,7 +325,7 @@ unit cgcpu;
|
|||||||
end
|
end
|
||||||
{ Routines with the poclearstack flag set use only a ret }
|
{ Routines with the poclearstack flag set use only a ret }
|
||||||
else if (current_procinfo.procdef.proccalloption in clearstack_pocalls) and
|
else if (current_procinfo.procdef.proccalloption in clearstack_pocalls) and
|
||||||
(not use_fixed_stack) then
|
(not paramanager.use_fixed_stack) then
|
||||||
begin
|
begin
|
||||||
{ complex return values are removed from stack in C code PM }
|
{ complex return values are removed from stack in C code PM }
|
||||||
{ but not on win32 }
|
{ but not on win32 }
|
||||||
@ -361,7 +361,7 @@ unit cgcpu;
|
|||||||
again,ok : tasmlabel;
|
again,ok : tasmlabel;
|
||||||
{$endif}
|
{$endif}
|
||||||
begin
|
begin
|
||||||
if use_fixed_stack then
|
if paramanager.use_fixed_stack then
|
||||||
begin
|
begin
|
||||||
inherited g_copyvaluepara_openarray(list,ref,lenloc,elesize,destreg);
|
inherited g_copyvaluepara_openarray(list,ref,lenloc,elesize,destreg);
|
||||||
exit;
|
exit;
|
||||||
@ -471,7 +471,7 @@ unit cgcpu;
|
|||||||
|
|
||||||
procedure tcg386.g_releasevaluepara_openarray(list : TAsmList;const l:tlocation);
|
procedure tcg386.g_releasevaluepara_openarray(list : TAsmList;const l:tlocation);
|
||||||
begin
|
begin
|
||||||
if use_fixed_stack then
|
if paramanager.use_fixed_stack then
|
||||||
begin
|
begin
|
||||||
inherited g_releasevaluepara_openarray(list,l);
|
inherited g_releasevaluepara_openarray(list,l);
|
||||||
exit;
|
exit;
|
||||||
@ -482,7 +482,7 @@ unit cgcpu;
|
|||||||
|
|
||||||
procedure tcg386.g_exception_reason_save(list : TAsmList; const href : treference);
|
procedure tcg386.g_exception_reason_save(list : TAsmList; const href : treference);
|
||||||
begin
|
begin
|
||||||
if not use_fixed_stack then
|
if not paramanager.use_fixed_stack then
|
||||||
list.concat(Taicpu.op_reg(A_PUSH,tcgsize2opsize[OS_INT],NR_FUNCTION_RESULT_REG))
|
list.concat(Taicpu.op_reg(A_PUSH,tcgsize2opsize[OS_INT],NR_FUNCTION_RESULT_REG))
|
||||||
else
|
else
|
||||||
inherited g_exception_reason_save(list,href);
|
inherited g_exception_reason_save(list,href);
|
||||||
@ -491,7 +491,7 @@ unit cgcpu;
|
|||||||
|
|
||||||
procedure tcg386.g_exception_reason_save_const(list : TAsmList;const href : treference; a: aint);
|
procedure tcg386.g_exception_reason_save_const(list : TAsmList;const href : treference; a: aint);
|
||||||
begin
|
begin
|
||||||
if not use_fixed_stack then
|
if not paramanager.use_fixed_stack then
|
||||||
list.concat(Taicpu.op_const(A_PUSH,tcgsize2opsize[OS_INT],a))
|
list.concat(Taicpu.op_const(A_PUSH,tcgsize2opsize[OS_INT],a))
|
||||||
else
|
else
|
||||||
inherited g_exception_reason_save_const(list,href,a);
|
inherited g_exception_reason_save_const(list,href,a);
|
||||||
@ -500,7 +500,7 @@ unit cgcpu;
|
|||||||
|
|
||||||
procedure tcg386.g_exception_reason_load(list : TAsmList; const href : treference);
|
procedure tcg386.g_exception_reason_load(list : TAsmList; const href : treference);
|
||||||
begin
|
begin
|
||||||
if not use_fixed_stack then
|
if not paramanager.use_fixed_stack then
|
||||||
begin
|
begin
|
||||||
cg.a_reg_alloc(list,NR_FUNCTION_RESULT_REG);
|
cg.a_reg_alloc(list,NR_FUNCTION_RESULT_REG);
|
||||||
list.concat(Taicpu.op_reg(A_POP,tcgsize2opsize[OS_INT],NR_FUNCTION_RESULT_REG))
|
list.concat(Taicpu.op_reg(A_POP,tcgsize2opsize[OS_INT],NR_FUNCTION_RESULT_REG))
|
||||||
|
|||||||
@ -48,7 +48,7 @@ unit cpupara;
|
|||||||
procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
|
procedure getintparaloc(calloption : tproccalloption; nr : longint;var cgpara:TCGPara);override;
|
||||||
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
|
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
|
||||||
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
|
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;override;
|
||||||
procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);override;
|
procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);override;
|
||||||
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): TCGPara;override;
|
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): TCGPara;override;
|
||||||
private
|
private
|
||||||
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
||||||
@ -735,19 +735,16 @@ unit cpupara;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure ti386paramanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
|
procedure ti386paramanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);
|
||||||
var
|
var
|
||||||
paraloc : pcgparalocation;
|
paraloc : pcgparalocation;
|
||||||
begin
|
begin
|
||||||
paraloc:=parasym.paraloc[callerside].location;
|
paraloc:=parasym.paraloc[callerside].location;
|
||||||
{ No need for temps when value is pushed }
|
{ Never a need for temps when value is pushed (calls inside parameters
|
||||||
if not(use_fixed_stack) and
|
will simply allocate even more stack space for their parameters) }
|
||||||
assigned(paraloc) and
|
if not(use_fixed_stack) then
|
||||||
(paraloc^.loc=LOC_REFERENCE) and
|
can_use_final_stack_loc:=true;
|
||||||
(paraloc^.reference.index=NR_STACK_POINTER_REG) then
|
inherited createtempparaloc(list,calloption,parasym,can_use_final_stack_loc,cgpara);
|
||||||
duplicateparaloc(list,calloption,parasym,cgpara)
|
|
||||||
else
|
|
||||||
inherited createtempparaloc(list,calloption,parasym,cgpara);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -45,7 +45,7 @@ unit cpupi;
|
|||||||
uses
|
uses
|
||||||
cutils,
|
cutils,
|
||||||
systems,globals,globtype,
|
systems,globals,globtype,
|
||||||
cgobj,tgobj,
|
cgobj,tgobj,paramgr,
|
||||||
cpubase,
|
cpubase,
|
||||||
cgutils,
|
cgutils,
|
||||||
symconst;
|
symconst;
|
||||||
@ -59,7 +59,7 @@ unit cpupi;
|
|||||||
|
|
||||||
procedure ti386procinfo.set_first_temp_offset;
|
procedure ti386procinfo.set_first_temp_offset;
|
||||||
begin
|
begin
|
||||||
if use_fixed_stack then
|
if paramanager.use_fixed_stack then
|
||||||
begin
|
begin
|
||||||
if not(po_assembler in procdef.procoptions) and
|
if not(po_assembler in procdef.procoptions) and
|
||||||
(tg.direction > 0) then
|
(tg.direction > 0) then
|
||||||
@ -85,7 +85,7 @@ unit cpupi;
|
|||||||
{ Para_stack_size is only used to determine how many bytes to remove }
|
{ Para_stack_size is only used to determine how many bytes to remove }
|
||||||
{ from the stack at the end of the procedure (in the "ret $xx"). }
|
{ from the stack at the end of the procedure (in the "ret $xx"). }
|
||||||
{ If the stack is fixed, nothing has to be removed by the callee }
|
{ If the stack is fixed, nothing has to be removed by the callee }
|
||||||
if use_fixed_stack then
|
if paramanager.use_fixed_stack then
|
||||||
para_stack_size := 0;
|
para_stack_size := 0;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
@ -69,7 +69,7 @@ implementation
|
|||||||
var
|
var
|
||||||
hreg : tregister;
|
hreg : tregister;
|
||||||
begin
|
begin
|
||||||
if (use_fixed_stack) then
|
if (paramanager.use_fixed_stack) then
|
||||||
begin
|
begin
|
||||||
{ very weird: in this case the callee does a "ret $4" and the }
|
{ very weird: in this case the callee does a "ret $4" and the }
|
||||||
{ caller immediately a "subl $4,%esp". Possibly this is for }
|
{ caller immediately a "subl $4,%esp". Possibly this is for }
|
||||||
|
|||||||
@ -206,7 +206,7 @@ unit cgcpu;
|
|||||||
|
|
||||||
function use_push(const cgpara:tcgpara):boolean;
|
function use_push(const cgpara:tcgpara):boolean;
|
||||||
begin
|
begin
|
||||||
result:=(not use_fixed_stack) and
|
result:=(not paramanager.use_fixed_stack) and
|
||||||
assigned(cgpara.location) and
|
assigned(cgpara.location) and
|
||||||
(cgpara.location^.loc=LOC_REFERENCE) and
|
(cgpara.location^.loc=LOC_REFERENCE) and
|
||||||
(cgpara.location^.reference.index=NR_STACK_POINTER_REG);
|
(cgpara.location^.reference.index=NR_STACK_POINTER_REG);
|
||||||
|
|||||||
@ -45,7 +45,7 @@ unit cpupara;
|
|||||||
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
|
function create_paraloc_info(p : tabstractprocdef; side: tcallercallee):longint;override;
|
||||||
function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
|
function push_addr_param(varspez:tvarspez;def : tdef;calloption : tproccalloption) : boolean;override;
|
||||||
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
|
function get_funcretloc(p : tabstractprocdef; side: tcallercallee; def: tdef): tcgpara;override;
|
||||||
procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);override;
|
procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);
|
||||||
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
procedure create_funcretloc_info(p : tabstractprocdef; side: tcallercallee);
|
||||||
private
|
private
|
||||||
procedure init_values(var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword);
|
procedure init_values(var curintreg, curfloatreg: tsuperregister; var cur_stack_offset: aword);
|
||||||
@ -565,22 +565,18 @@ unit cpupara;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure tm68kparamanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
|
procedure tm68kparamanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);
|
||||||
var
|
var
|
||||||
paraloc : pcgparalocation;
|
paraloc : pcgparalocation;
|
||||||
begin
|
begin
|
||||||
paraloc:=parasym.paraloc[callerside].location;
|
paraloc:=parasym.paraloc[callerside].location;
|
||||||
{ No need for temps when value is pushed }
|
{ Never a need for temps when value is pushed (calls inside parameters
|
||||||
if not(use_fixed_stack) and
|
will simply allocate even more stack space for their parameters) }
|
||||||
assigned(paraloc) and
|
if not(use_fixed_stack) then
|
||||||
(paraloc^.loc=LOC_REFERENCE) and
|
can_use_final_stack_loc:=true;
|
||||||
(paraloc^.reference.index=NR_STACK_POINTER_REG) then
|
inherited createtempparaloc(list,calloption,parasym,can_use_final_stack_loc,cgpara);
|
||||||
duplicateparaloc(list,calloption,parasym,cgpara)
|
|
||||||
else
|
|
||||||
inherited createtempparaloc(list,calloption,parasym,cgpara);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
paramanager:=tm68kparamanager.create;
|
paramanager:=tm68kparamanager.create;
|
||||||
end.
|
end.
|
||||||
|
|||||||
@ -174,6 +174,9 @@ interface
|
|||||||
tcallparaflags = set of tcallparaflag;
|
tcallparaflags = set of tcallparaflag;
|
||||||
|
|
||||||
tcallparanode = class(ttertiarynode)
|
tcallparanode = class(ttertiarynode)
|
||||||
|
private
|
||||||
|
fcontains_stack_tainting_call_cached,
|
||||||
|
ffollowed_by_stack_tainting_call_cached : boolean;
|
||||||
public
|
public
|
||||||
callparaflags : tcallparaflags;
|
callparaflags : tcallparaflags;
|
||||||
parasym : tparavarsym;
|
parasym : tparavarsym;
|
||||||
@ -199,6 +202,21 @@ interface
|
|||||||
|
|
||||||
property nextpara : tnode read right write right;
|
property nextpara : tnode read right write right;
|
||||||
property parametername : tnode read third write third;
|
property parametername : tnode read third write third;
|
||||||
|
|
||||||
|
{ returns whether the evaluation of this parameter involves a
|
||||||
|
stack tainting call }
|
||||||
|
function contains_stack_tainting_call: boolean;
|
||||||
|
{ initialises the fcontains_stack_tainting_call_cached field with the
|
||||||
|
result of contains_stack_tainting_call so that it can be quickly
|
||||||
|
accessed via the contains_stack_tainting_call_cached property }
|
||||||
|
procedure init_contains_stack_tainting_call_cache;
|
||||||
|
{ returns result of contains_stack_tainting_call cached during last
|
||||||
|
call to init_contains_stack_tainting_call_cache }
|
||||||
|
property contains_stack_tainting_call_cached: boolean read fcontains_stack_tainting_call_cached;
|
||||||
|
{ returns whether this parameter is followed by at least one other
|
||||||
|
parameter whose evaluation involves a stack tainting parameter
|
||||||
|
(result is only valid after order_parameters has been called) }
|
||||||
|
property followed_by_stack_tainting_call_cached: boolean read ffollowed_by_stack_tainting_call_cached;
|
||||||
end;
|
end;
|
||||||
tcallparanodeclass = class of tcallparanode;
|
tcallparanodeclass = class of tcallparanode;
|
||||||
|
|
||||||
@ -962,6 +980,28 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function check_contains_stack_tainting_call(var n: tnode; arg: pointer): foreachnoderesult;
|
||||||
|
begin
|
||||||
|
if (n.nodetype=calln) and
|
||||||
|
tcallnode(n).procdefinition.stack_tainting_parameter(callerside) then
|
||||||
|
result:=fen_norecurse_true
|
||||||
|
else
|
||||||
|
result:=fen_false;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function tcallparanode.contains_stack_tainting_call: boolean;
|
||||||
|
begin
|
||||||
|
result:=foreachnodestatic(pm_postprocess,left,@check_contains_stack_tainting_call,nil);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure tcallparanode.init_contains_stack_tainting_call_cache;
|
||||||
|
begin
|
||||||
|
fcontains_stack_tainting_call_cached:=contains_stack_tainting_call;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function tcallparanode.docompare(p: tnode): boolean;
|
function tcallparanode.docompare(p: tnode): boolean;
|
||||||
begin
|
begin
|
||||||
docompare :=
|
docompare :=
|
||||||
@ -2998,6 +3038,14 @@ implementation
|
|||||||
begin
|
begin
|
||||||
hpfirst:=nil;
|
hpfirst:=nil;
|
||||||
hpcurr:=tcallparanode(left);
|
hpcurr:=tcallparanode(left);
|
||||||
|
{ cache all info about parameters containing stack tainting calls,
|
||||||
|
since we will need it a lot below and calculting it can be expensive }
|
||||||
|
while assigned(hpcurr) do
|
||||||
|
begin
|
||||||
|
hpcurr.init_contains_stack_tainting_call_cache;
|
||||||
|
hpcurr:=tcallparanode(hpcurr.right);
|
||||||
|
end;
|
||||||
|
hpcurr:=tcallparanode(left);
|
||||||
while assigned(hpcurr) do
|
while assigned(hpcurr) do
|
||||||
begin
|
begin
|
||||||
{ pull out }
|
{ pull out }
|
||||||
@ -3030,8 +3078,17 @@ implementation
|
|||||||
currloc:=hpcurr.parasym.paraloc[callerside].location^.loc;
|
currloc:=hpcurr.parasym.paraloc[callerside].location^.loc;
|
||||||
hpprev:=nil;
|
hpprev:=nil;
|
||||||
hp:=hpfirst;
|
hp:=hpfirst;
|
||||||
|
{ on fixed_stack targets, always evaluate parameters containing
|
||||||
|
a call with stack parameters before all other parameters,
|
||||||
|
because they will prevent any other parameters from being put
|
||||||
|
in their final place; if both the current and the next para
|
||||||
|
contain a stack tainting call, don't do anything to prevent
|
||||||
|
them from keeping on chasing eachother's tail }
|
||||||
while assigned(hp) do
|
while assigned(hp) do
|
||||||
begin
|
begin
|
||||||
|
if paramanager.use_fixed_stack and
|
||||||
|
hpcurr.contains_stack_tainting_call_cached then
|
||||||
|
break;
|
||||||
case currloc of
|
case currloc of
|
||||||
LOC_REFERENCE :
|
LOC_REFERENCE :
|
||||||
begin
|
begin
|
||||||
@ -3050,8 +3107,11 @@ implementation
|
|||||||
{$ifdef i386}
|
{$ifdef i386}
|
||||||
{ the i386 code generator expects all reference }
|
{ the i386 code generator expects all reference }
|
||||||
{ parameter to be in this order so it can use }
|
{ parameter to be in this order so it can use }
|
||||||
{ pushes }
|
{ pushes in case of no fixed stack }
|
||||||
if (hpcurr.parasym.paraloc[callerside].location^.reference.offset>hp.parasym.paraloc[callerside].location^.reference.offset) then
|
if (not paramanager.use_fixed_stack and
|
||||||
|
(hpcurr.parasym.paraloc[callerside].location^.reference.offset>hp.parasym.paraloc[callerside].location^.reference.offset)) or
|
||||||
|
(paramanager.use_fixed_stack and
|
||||||
|
(node_complexity(hpcurr)<node_complexity(hp))) then
|
||||||
{$else i386}
|
{$else i386}
|
||||||
if (node_complexity(hpcurr)<node_complexity(hp)) then
|
if (node_complexity(hpcurr)<node_complexity(hp)) then
|
||||||
{$endif i386}
|
{$endif i386}
|
||||||
@ -3084,6 +3144,30 @@ implementation
|
|||||||
hpcurr:=hpnext;
|
hpcurr:=hpnext;
|
||||||
end;
|
end;
|
||||||
left:=hpfirst;
|
left:=hpfirst;
|
||||||
|
{ now mark each parameter that is followed by a stack-tainting call,
|
||||||
|
to determine on use_fixed_stack targets which ones can immediately be
|
||||||
|
put in their final destination. Unforunately we can never put register
|
||||||
|
parameters immediately in their final destination (even on register-
|
||||||
|
rich architectures such as the PowerPC), because the code generator
|
||||||
|
can still insert extra calls that only make use of register
|
||||||
|
parameters (fpc_move() etc. }
|
||||||
|
hpcurr:=hpfirst;
|
||||||
|
while assigned(hpcurr) do
|
||||||
|
begin
|
||||||
|
if hpcurr.contains_stack_tainting_call_cached then
|
||||||
|
begin
|
||||||
|
{ all parameters before this one are followed by a stack
|
||||||
|
tainting call }
|
||||||
|
hp:=hpfirst;
|
||||||
|
while hp<>hpcurr do
|
||||||
|
begin
|
||||||
|
hp.ffollowed_by_stack_tainting_call_cached:=true;
|
||||||
|
hp:=tcallparanode(hp.right);
|
||||||
|
end;
|
||||||
|
hpfirst:=hpcurr;
|
||||||
|
end;
|
||||||
|
hpcurr:=tcallparanode(hpcurr.right);
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -3206,17 +3290,13 @@ implementation
|
|||||||
result:=nil;
|
result:=nil;
|
||||||
|
|
||||||
{ calculate the parameter info for the procdef }
|
{ calculate the parameter info for the procdef }
|
||||||
if not procdefinition.has_paraloc_info then
|
procdefinition.init_paraloc_info(callerside);
|
||||||
begin
|
|
||||||
procdefinition.requiredargarea:=paramanager.create_paraloc_info(procdefinition,callerside);
|
|
||||||
procdefinition.has_paraloc_info:=true;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ calculate the parameter size needed for this call include varargs if they are available }
|
{ calculate the parameter size needed for this call include varargs if they are available }
|
||||||
if assigned(varargsparas) then
|
if assigned(varargsparas) then
|
||||||
pushedparasize:=paramanager.create_varargs_paraloc_info(procdefinition,varargsparas)
|
pushedparasize:=paramanager.create_varargs_paraloc_info(procdefinition,varargsparas)
|
||||||
else
|
else
|
||||||
pushedparasize:=procdefinition.requiredargarea;
|
pushedparasize:=procdefinition.callerargareasize;
|
||||||
|
|
||||||
{ record maximum parameter size used in this proc }
|
{ record maximum parameter size used in this proc }
|
||||||
current_procinfo.allocate_push_parasize(pushedparasize);
|
current_procinfo.allocate_push_parasize(pushedparasize);
|
||||||
|
|||||||
@ -170,7 +170,7 @@ implementation
|
|||||||
cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
|
cg.g_decrrefcount(current_asmdata.CurrAsmList,left.resultdef,href);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
paramanager.createtempparaloc(current_asmdata.CurrAsmList,aktcallnode.procdefinition.proccalloption,parasym,tempcgpara);
|
paramanager.createtempparaloc(current_asmdata.CurrAsmList,aktcallnode.procdefinition.proccalloption,parasym,not followed_by_stack_tainting_call_cached,tempcgpara);
|
||||||
|
|
||||||
{ handle varargs first, because parasym is not valid }
|
{ handle varargs first, because parasym is not valid }
|
||||||
if (cpf_varargs_para in callparaflags) then
|
if (cpf_varargs_para in callparaflags) then
|
||||||
@ -485,6 +485,7 @@ implementation
|
|||||||
href : treference;
|
href : treference;
|
||||||
calleralignment,
|
calleralignment,
|
||||||
tmpalignment: longint;
|
tmpalignment: longint;
|
||||||
|
skipmemloc: boolean;
|
||||||
begin
|
begin
|
||||||
{ copy all resources to the allocated registers }
|
{ copy all resources to the allocated registers }
|
||||||
ppn:=tcgcallparanode(left);
|
ppn:=tcgcallparanode(left);
|
||||||
@ -504,6 +505,10 @@ implementation
|
|||||||
(calleralignment=0) then
|
(calleralignment=0) then
|
||||||
internalerror(2009020701);
|
internalerror(2009020701);
|
||||||
callerparaloc:=ppn.parasym.paraloc[callerside].location;
|
callerparaloc:=ppn.parasym.paraloc[callerside].location;
|
||||||
|
skipmemloc:=
|
||||||
|
(not paramanager.use_fixed_stack or
|
||||||
|
not(ppn.followed_by_stack_tainting_call_cached)) and
|
||||||
|
paramanager.is_simple_stack_paraloc(callerparaloc);
|
||||||
while assigned(callerparaloc) do
|
while assigned(callerparaloc) do
|
||||||
begin
|
begin
|
||||||
{ Every paraloc must have a matching tmpparaloc }
|
{ Every paraloc must have a matching tmpparaloc }
|
||||||
@ -540,7 +545,7 @@ implementation
|
|||||||
end;
|
end;
|
||||||
LOC_REFERENCE:
|
LOC_REFERENCE:
|
||||||
begin
|
begin
|
||||||
if use_fixed_stack then
|
if not skipmemloc then
|
||||||
begin
|
begin
|
||||||
{ Can't have a data copied to the stack, every location
|
{ Can't have a data copied to the stack, every location
|
||||||
must contain a valid size field }
|
must contain a valid size field }
|
||||||
@ -624,7 +629,7 @@ implementation
|
|||||||
{$endif x86_64}
|
{$endif x86_64}
|
||||||
begin
|
begin
|
||||||
if not assigned(procdefinition) or
|
if not assigned(procdefinition) or
|
||||||
not procdefinition.has_paraloc_info then
|
not(procdefinition.has_paraloc_info in [callerside,callbothsides]) then
|
||||||
internalerror(200305264);
|
internalerror(200305264);
|
||||||
|
|
||||||
if assigned(callinitblock) then
|
if assigned(callinitblock) then
|
||||||
@ -852,7 +857,7 @@ implementation
|
|||||||
{ frame pointer parameter is popped by the caller when it's passed the
|
{ frame pointer parameter is popped by the caller when it's passed the
|
||||||
Delphi way }
|
Delphi way }
|
||||||
else if (po_delphi_nested_cc in procdefinition.procoptions) and
|
else if (po_delphi_nested_cc in procdefinition.procoptions) and
|
||||||
not use_fixed_stack then
|
not paramanager.use_fixed_stack then
|
||||||
pop_parasize(sizeof(pint));
|
pop_parasize(sizeof(pint));
|
||||||
{ Release registers, but not the registers that contain the
|
{ Release registers, but not the registers that contain the
|
||||||
function result }
|
function result }
|
||||||
|
|||||||
@ -235,7 +235,7 @@ implementation
|
|||||||
LOC_REFERENCE,
|
LOC_REFERENCE,
|
||||||
LOC_CREFERENCE :
|
LOC_CREFERENCE :
|
||||||
begin
|
begin
|
||||||
if use_fixed_stack then
|
if paramanager.use_fixed_stack then
|
||||||
location_freetemp(list,location);
|
location_freetemp(list,location);
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
@ -805,7 +805,7 @@ implementation
|
|||||||
LOC_REFERENCE:
|
LOC_REFERENCE:
|
||||||
begin
|
begin
|
||||||
size:=align(locintsize,cgpara.alignment);
|
size:=align(locintsize,cgpara.alignment);
|
||||||
if (not use_fixed_stack) and
|
if (not paramanager.use_fixed_stack) and
|
||||||
(cgpara.location^.reference.index=NR_STACK_POINTER_REG) then
|
(cgpara.location^.reference.index=NR_STACK_POINTER_REG) then
|
||||||
begin
|
begin
|
||||||
cg.g_stackpointer_alloc(list,size);
|
cg.g_stackpointer_alloc(list,size);
|
||||||
@ -850,7 +850,7 @@ implementation
|
|||||||
{ can't use TCGSize2Size[l.size], because the size of an
|
{ can't use TCGSize2Size[l.size], because the size of an
|
||||||
80 bit extended parameter can be either 10 or 12 bytes }
|
80 bit extended parameter can be either 10 or 12 bytes }
|
||||||
size:=align(locintsize,cgpara.alignment);
|
size:=align(locintsize,cgpara.alignment);
|
||||||
if (not use_fixed_stack) and
|
if (not paramanager.use_fixed_stack) and
|
||||||
(cgpara.location^.reference.index=NR_STACK_POINTER_REG) then
|
(cgpara.location^.reference.index=NR_STACK_POINTER_REG) then
|
||||||
begin
|
begin
|
||||||
cg.g_stackpointer_alloc(list,size);
|
cg.g_stackpointer_alloc(list,size);
|
||||||
@ -878,7 +878,7 @@ implementation
|
|||||||
LOC_REFERENCE:
|
LOC_REFERENCE:
|
||||||
begin
|
begin
|
||||||
size:=align(locintsize,cgpara.alignment);
|
size:=align(locintsize,cgpara.alignment);
|
||||||
if (not use_fixed_stack) and
|
if (not paramanager.use_fixed_stack) and
|
||||||
(cgpara.location^.reference.index=NR_STACK_POINTER_REG) then
|
(cgpara.location^.reference.index=NR_STACK_POINTER_REG) then
|
||||||
cg.a_load_ref_cgpara(list,locsize,l.reference,cgpara)
|
cg.a_load_ref_cgpara(list,locsize,l.reference,cgpara)
|
||||||
else
|
else
|
||||||
@ -2347,7 +2347,7 @@ implementation
|
|||||||
parasize:=current_procinfo.para_stack_size;
|
parasize:=current_procinfo.para_stack_size;
|
||||||
{ the parent frame pointer para has to be removed by the caller in
|
{ the parent frame pointer para has to be removed by the caller in
|
||||||
case of Delphi-style parent frame pointer passing }
|
case of Delphi-style parent frame pointer passing }
|
||||||
if not use_fixed_stack and
|
if not paramanager.use_fixed_stack and
|
||||||
(po_delphi_nested_cc in current_procinfo.procdef.procoptions) then
|
(po_delphi_nested_cc in current_procinfo.procdef.procoptions) then
|
||||||
dec(parasize,sizeof(pint));
|
dec(parasize,sizeof(pint));
|
||||||
end;
|
end;
|
||||||
|
|||||||
@ -205,11 +205,7 @@ end;
|
|||||||
begin
|
begin
|
||||||
result:='';
|
result:='';
|
||||||
totalsize:=0;
|
totalsize:=0;
|
||||||
if not pd.has_paraloc_info then
|
pd.init_paraloc_info(callerside);
|
||||||
begin
|
|
||||||
pd.requiredargarea:=paramanager.create_paraloc_info(pd,callerside);
|
|
||||||
pd.has_paraloc_info:=true;
|
|
||||||
end;
|
|
||||||
{$if defined(powerpc) and defined(dummy)}
|
{$if defined(powerpc) and defined(dummy)}
|
||||||
{ Disabled, because neither Clang nor gcc does this, and the ObjC
|
{ Disabled, because neither Clang nor gcc does this, and the ObjC
|
||||||
runtime contains an explicit fix to detect this error. }
|
runtime contains an explicit fix to detect this error. }
|
||||||
|
|||||||
@ -38,6 +38,9 @@ unit paramgr;
|
|||||||
{# This class defines some methods to take care of routine
|
{# This class defines some methods to take care of routine
|
||||||
parameters. It should be overriden for each new processor
|
parameters. It should be overriden for each new processor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ tparamanager }
|
||||||
|
|
||||||
tparamanager = class
|
tparamanager = class
|
||||||
{ true if the location in paraloc can be reused as localloc }
|
{ true if the location in paraloc can be reused as localloc }
|
||||||
function param_use_paraloc(const cgpara:tcgpara):boolean;virtual;
|
function param_use_paraloc(const cgpara:tcgpara):boolean;virtual;
|
||||||
@ -121,11 +124,15 @@ unit paramgr;
|
|||||||
}
|
}
|
||||||
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;virtual;abstract;
|
function create_varargs_paraloc_info(p : tabstractprocdef; varargspara:tvarargsparalist):longint;virtual;abstract;
|
||||||
|
|
||||||
procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);virtual;
|
function is_simple_stack_paraloc(paraloc: pcgparalocation): boolean;
|
||||||
|
procedure createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);virtual;
|
||||||
procedure duplicateparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
|
procedure duplicateparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
|
||||||
|
|
||||||
function parseparaloc(parasym : tparavarsym;const s : string) : boolean;virtual;
|
function parseparaloc(parasym : tparavarsym;const s : string) : boolean;virtual;
|
||||||
function parsefuncretloc(p : tabstractprocdef; const s : string) : boolean;virtual;
|
function parsefuncretloc(p : tabstractprocdef; const s : string) : boolean;virtual;
|
||||||
|
|
||||||
|
{ allocate room for parameters on the stack in the entry code? }
|
||||||
|
function use_fixed_stack: boolean;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -320,13 +327,31 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure tparamanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
|
function tparamanager.is_simple_stack_paraloc(paraloc: pcgparalocation): boolean;
|
||||||
|
begin
|
||||||
|
result:=
|
||||||
|
assigned(paraloc) and
|
||||||
|
(paraloc^.loc=LOC_REFERENCE) and
|
||||||
|
(paraloc^.reference.index=NR_STACK_POINTER_REG) and
|
||||||
|
not assigned(paraloc^.next);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure tparamanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;can_use_final_stack_loc : boolean;var cgpara:TCGPara);
|
||||||
var
|
var
|
||||||
href : treference;
|
href : treference;
|
||||||
len : aint;
|
len : aint;
|
||||||
paraloc,
|
paraloc,
|
||||||
newparaloc : pcgparalocation;
|
newparaloc : pcgparalocation;
|
||||||
begin
|
begin
|
||||||
|
paraloc:=parasym.paraloc[callerside].location;
|
||||||
|
if can_use_final_stack_loc and
|
||||||
|
is_simple_stack_paraloc(paraloc) then
|
||||||
|
begin
|
||||||
|
duplicateparaloc(list,calloption,parasym,cgpara);
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
cgpara.reset;
|
cgpara.reset;
|
||||||
cgpara.size:=parasym.paraloc[callerside].size;
|
cgpara.size:=parasym.paraloc[callerside].size;
|
||||||
cgpara.intsize:=parasym.paraloc[callerside].intsize;
|
cgpara.intsize:=parasym.paraloc[callerside].intsize;
|
||||||
@ -334,7 +359,6 @@ implementation
|
|||||||
{$ifdef powerpc}
|
{$ifdef powerpc}
|
||||||
cgpara.composite:=parasym.paraloc[callerside].composite;
|
cgpara.composite:=parasym.paraloc[callerside].composite;
|
||||||
{$endif powerpc}
|
{$endif powerpc}
|
||||||
paraloc:=parasym.paraloc[callerside].location;
|
|
||||||
while assigned(paraloc) do
|
while assigned(paraloc) do
|
||||||
begin
|
begin
|
||||||
if paraloc^.size=OS_NO then
|
if paraloc^.size=OS_NO then
|
||||||
@ -398,8 +422,8 @@ implementation
|
|||||||
function tparamanager.create_inline_paraloc_info(p : tabstractprocdef):longint;
|
function tparamanager.create_inline_paraloc_info(p : tabstractprocdef):longint;
|
||||||
begin
|
begin
|
||||||
{ We need to return the size allocated }
|
{ We need to return the size allocated }
|
||||||
create_paraloc_info(p,callerside);
|
p.init_paraloc_info(callbothsides);
|
||||||
result:=create_paraloc_info(p,calleeside);
|
result:=p.calleeargareasize;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -416,6 +440,21 @@ implementation
|
|||||||
internalerror(200807236);
|
internalerror(200807236);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function tparamanager.use_fixed_stack: boolean;
|
||||||
|
begin
|
||||||
|
{$ifdef i386}
|
||||||
|
result := (target_info.system in [system_i386_darwin,system_x86_64_darwin]);
|
||||||
|
{$else i386}
|
||||||
|
{$ifdef cputargethasfixedstack}
|
||||||
|
result := true;
|
||||||
|
{$else cputargethasfixedstack}
|
||||||
|
result := false;
|
||||||
|
{$endif cputargethasfixedstack}
|
||||||
|
{$endif i386}
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
;
|
;
|
||||||
finalization
|
finalization
|
||||||
|
|||||||
@ -699,7 +699,7 @@ implementation
|
|||||||
|
|
||||||
if explicit_paraloc then
|
if explicit_paraloc then
|
||||||
begin
|
begin
|
||||||
pd.has_paraloc_info:=true;
|
pd.has_paraloc_info:=callerside;
|
||||||
include(pd.procoptions,po_explicitparaloc);
|
include(pd.procoptions,po_explicitparaloc);
|
||||||
end;
|
end;
|
||||||
{ remove parasymtable from stack }
|
{ remove parasymtable from stack }
|
||||||
|
|||||||
@ -704,26 +704,6 @@ unit cpupara;
|
|||||||
result:=true;
|
result:=true;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
breaks e.g. tests/test/cg/tpara1
|
|
||||||
|
|
||||||
procedure tppcparamanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
|
|
||||||
var
|
|
||||||
paraloc : pcgparalocation;
|
|
||||||
begin
|
|
||||||
paraloc:=parasym.paraloc[callerside].location;
|
|
||||||
{ No need for temps when value is pushed }
|
|
||||||
if assigned(paraloc) and
|
|
||||||
(paraloc^.loc=LOC_REFERENCE) and
|
|
||||||
(paraloc^.reference.index=NR_STACK_POINTER_REG) then
|
|
||||||
duplicateparaloc(list,calloption,parasym,cgpara)
|
|
||||||
else
|
|
||||||
inherited createtempparaloc(list,calloption,parasym,cgpara);
|
|
||||||
end;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
paramanager:=tppcparamanager.create;
|
paramanager:=tppcparamanager.create;
|
||||||
end.
|
end.
|
||||||
|
|||||||
@ -520,25 +520,6 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{
|
|
||||||
|
|
||||||
breaks e.g. tests/test/cg/tpara1
|
|
||||||
|
|
||||||
procedure tppcparamanager.createtempparaloc(list: TAsmList;calloption : tproccalloption;parasym : tparavarsym;var cgpara:TCGPara);
|
|
||||||
var
|
|
||||||
paraloc : pcgparalocation;
|
|
||||||
begin
|
|
||||||
paraloc:=parasym.paraloc[callerside].location;
|
|
||||||
{ Do not create a temporary if the value is pushed }
|
|
||||||
if assigned(paraloc) and
|
|
||||||
(paraloc^.loc=LOC_REFERENCE) and
|
|
||||||
(paraloc^.reference.index=NR_STACK_POINTER_REG) then
|
|
||||||
duplicateparaloc(list,calloption,parasym,cgpara)
|
|
||||||
else
|
|
||||||
inherited createtempparaloc(list,calloption,parasym,cgpara);
|
|
||||||
end;
|
|
||||||
}
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
paramanager := tppcparamanager.create;
|
paramanager := tppcparamanager.create;
|
||||||
end.
|
end.
|
||||||
|
|||||||
@ -68,7 +68,7 @@ unit procinfo;
|
|||||||
exitswitches : tlocalswitches;
|
exitswitches : tlocalswitches;
|
||||||
|
|
||||||
{ Size of the parameters on the stack }
|
{ Size of the parameters on the stack }
|
||||||
para_stack_size : longint;
|
para_stack_size : pint;
|
||||||
|
|
||||||
{ Offset of temp after para/local are allocated }
|
{ Offset of temp after para/local are allocated }
|
||||||
tempstart : longint;
|
tempstart : longint;
|
||||||
@ -195,9 +195,10 @@ implementation
|
|||||||
|
|
||||||
procedure tprocinfo.generate_parameter_info;
|
procedure tprocinfo.generate_parameter_info;
|
||||||
begin
|
begin
|
||||||
{ generate callee paraloc register info, it returns the size that
|
{ generate callee paraloc register info, it initialises the size that
|
||||||
is allocated on the stack }
|
is allocated on the stack }
|
||||||
para_stack_size:=paramanager.create_paraloc_info(procdef,calleeside);
|
procdef.init_paraloc_info(calleeside);
|
||||||
|
para_stack_size:=procdef.calleeargareasize;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -57,7 +57,6 @@ interface
|
|||||||
procedure remove_from_symtablestack;
|
procedure remove_from_symtablestack;
|
||||||
procedure parse_body;
|
procedure parse_body;
|
||||||
|
|
||||||
function stack_tainting_parameter : boolean;
|
|
||||||
function has_assembler_child : boolean;
|
function has_assembler_child : boolean;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -784,29 +783,6 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure check_for_stack(p:TObject;arg:pointer);
|
|
||||||
begin
|
|
||||||
if tsym(p).typ=paravarsym then
|
|
||||||
begin
|
|
||||||
{ check if there no parameter of the current procedure is stack dependend }
|
|
||||||
if is_open_array(tparavarsym(p).vardef) or
|
|
||||||
is_array_of_const(tparavarsym(p).vardef) then
|
|
||||||
pboolean(arg)^:=true;
|
|
||||||
if assigned(p) and
|
|
||||||
assigned(tparavarsym(p).paraloc[calleeside].location) and
|
|
||||||
(tparavarsym(p).paraloc[calleeside].location^.loc=LOC_REFERENCE) then
|
|
||||||
pboolean(arg)^:=true;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
function tcgprocinfo.stack_tainting_parameter : boolean;
|
|
||||||
begin
|
|
||||||
result:=false;
|
|
||||||
procdef.parast.SymList.ForEachCall(@check_for_stack,@result);
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
function tcgprocinfo.has_assembler_child : boolean;
|
function tcgprocinfo.has_assembler_child : boolean;
|
||||||
var
|
var
|
||||||
hp : tcgprocinfo;
|
hp : tcgprocinfo;
|
||||||
@ -1006,9 +982,10 @@ implementation
|
|||||||
parameters on the stack
|
parameters on the stack
|
||||||
|
|
||||||
calling generate_parameter_info doesn't hurt but it costs time
|
calling generate_parameter_info doesn't hurt but it costs time
|
||||||
|
(necessary to init para_stack_size)
|
||||||
}
|
}
|
||||||
generate_parameter_info;
|
generate_parameter_info;
|
||||||
if not(stack_tainting_parameter) and
|
if not(procdef.stack_tainting_parameter(calleeside)) and
|
||||||
not(has_assembler_child) and (para_stack_size=0) then
|
not(has_assembler_child) and (para_stack_size=0) then
|
||||||
begin
|
begin
|
||||||
{ Only need to set the framepointer }
|
{ Only need to set the framepointer }
|
||||||
@ -1049,11 +1026,7 @@ implementation
|
|||||||
|
|
||||||
{ 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) }
|
||||||
if not procdef.has_paraloc_info then
|
procdef.init_paraloc_info(callerside);
|
||||||
begin
|
|
||||||
procdef.requiredargarea:=paramanager.create_paraloc_info(procdef,callerside);
|
|
||||||
procdef.has_paraloc_info:=true;
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ generate code for the node tree }
|
{ generate code for the node tree }
|
||||||
do_secondpass(code);
|
do_secondpass(code);
|
||||||
|
|||||||
@ -225,7 +225,7 @@ type
|
|||||||
vt_normalvariant,vt_olevariant
|
vt_normalvariant,vt_olevariant
|
||||||
);
|
);
|
||||||
|
|
||||||
tcallercallee = (callerside,calleeside);
|
tcallercallee = (callnoside,callerside,calleeside,callbothsides);
|
||||||
|
|
||||||
{ basic type for tprocdef and tprocvardef }
|
{ basic type for tprocdef and tprocvardef }
|
||||||
tproctypeoption=(potype_none,
|
tproctypeoption=(potype_none,
|
||||||
|
|||||||
@ -403,7 +403,8 @@ interface
|
|||||||
proctypeoption : tproctypeoption;
|
proctypeoption : tproctypeoption;
|
||||||
proccalloption : tproccalloption;
|
proccalloption : tproccalloption;
|
||||||
procoptions : tprocoptions;
|
procoptions : tprocoptions;
|
||||||
requiredargarea : aint;
|
callerargareasize,
|
||||||
|
calleeargareasize: pint;
|
||||||
{ number of user visibile parameters }
|
{ number of user visibile parameters }
|
||||||
maxparacount,
|
maxparacount,
|
||||||
minparacount : byte;
|
minparacount : byte;
|
||||||
@ -411,7 +412,7 @@ interface
|
|||||||
exp_funcretloc : tregister; { explicit funcretloc for AmigaOS }
|
exp_funcretloc : tregister; { explicit funcretloc for AmigaOS }
|
||||||
{$endif}
|
{$endif}
|
||||||
funcretloc : array[tcallercallee] of TCGPara;
|
funcretloc : array[tcallercallee] of TCGPara;
|
||||||
has_paraloc_info : boolean; { paraloc info is available }
|
has_paraloc_info : tcallercallee; { paraloc info is available }
|
||||||
constructor create(dt:tdeftyp;level:byte);
|
constructor create(dt:tdeftyp;level:byte);
|
||||||
constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
|
constructor ppuload(dt:tdeftyp;ppufile:tcompilerppufile);
|
||||||
destructor destroy;override;
|
destructor destroy;override;
|
||||||
@ -424,6 +425,8 @@ interface
|
|||||||
function is_addressonly:boolean;virtual;
|
function is_addressonly:boolean;virtual;
|
||||||
function no_self_node:boolean;
|
function no_self_node:boolean;
|
||||||
procedure check_mark_as_nested;
|
procedure check_mark_as_nested;
|
||||||
|
procedure init_paraloc_info(side: tcallercallee);
|
||||||
|
function stack_tainting_parameter(side: tcallercallee): boolean;
|
||||||
private
|
private
|
||||||
procedure count_para(p:TObject;arg:pointer);
|
procedure count_para(p:TObject;arg:pointer);
|
||||||
procedure insert_para(p:TObject;arg:pointer);
|
procedure insert_para(p:TObject;arg:pointer);
|
||||||
@ -2760,8 +2763,9 @@ implementation
|
|||||||
procoptions:=[];
|
procoptions:=[];
|
||||||
returndef:=voidtype;
|
returndef:=voidtype;
|
||||||
savesize:=sizeof(pint);
|
savesize:=sizeof(pint);
|
||||||
requiredargarea:=0;
|
callerargareasize:=0;
|
||||||
has_paraloc_info:=false;
|
calleeargareasize:=0;
|
||||||
|
has_paraloc_info:=callnoside;
|
||||||
funcretloc[callerside].init;
|
funcretloc[callerside].init;
|
||||||
funcretloc[calleeside].init;
|
funcretloc[calleeside].init;
|
||||||
check_mark_as_nested;
|
check_mark_as_nested;
|
||||||
@ -2885,7 +2889,8 @@ implementation
|
|||||||
funcretloc[callerside].ppuload(ppufile);
|
funcretloc[callerside].ppuload(ppufile);
|
||||||
|
|
||||||
savesize:=sizeof(pint);
|
savesize:=sizeof(pint);
|
||||||
has_paraloc_info:=(po_explicitparaloc in procoptions);
|
if (po_explicitparaloc in procoptions) then
|
||||||
|
has_paraloc_info:=callerside;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -3035,6 +3040,53 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure tabstractprocdef.init_paraloc_info(side: tcallercallee);
|
||||||
|
begin
|
||||||
|
if (side in [callerside,callbothsides]) and
|
||||||
|
not(has_paraloc_info in [callerside,callbothsides]) then
|
||||||
|
begin
|
||||||
|
callerargareasize:=paramanager.create_paraloc_info(self,callerside);
|
||||||
|
if has_paraloc_info in [calleeside,callbothsides] then
|
||||||
|
has_paraloc_info:=callbothsides
|
||||||
|
else
|
||||||
|
has_paraloc_info:=callerside;
|
||||||
|
end;
|
||||||
|
if (side in [calleeside,callbothsides]) and
|
||||||
|
not(has_paraloc_info in [calleeside,callbothsides]) then
|
||||||
|
begin
|
||||||
|
calleeargareasize:=paramanager.create_paraloc_info(self,calleeside);
|
||||||
|
if has_paraloc_info in [callerside,callbothsides] then
|
||||||
|
has_paraloc_info:=callbothsides
|
||||||
|
else
|
||||||
|
has_paraloc_info:=calleeside;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function tabstractprocdef.stack_tainting_parameter(side: tcallercallee): boolean;
|
||||||
|
var
|
||||||
|
p: tparavarsym;
|
||||||
|
i: longint;
|
||||||
|
begin
|
||||||
|
result:=false;
|
||||||
|
init_paraloc_info(side);
|
||||||
|
for i:=0 to parast.SymList.Count-1 do
|
||||||
|
if tsym(parast.SymList[i]).typ=paravarsym then
|
||||||
|
begin
|
||||||
|
p:=tparavarsym(parast.SymList[i]);
|
||||||
|
{ check if no parameter is located on the stack }
|
||||||
|
if is_open_array(p.vardef) or
|
||||||
|
is_array_of_const(p.vardef) then
|
||||||
|
result:=true;
|
||||||
|
if assigned(p.paraloc[side].location) and
|
||||||
|
(p.paraloc[side].location^.loc=LOC_REFERENCE) then
|
||||||
|
result:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{***************************************************************************
|
{***************************************************************************
|
||||||
TPROCDEF
|
TPROCDEF
|
||||||
***************************************************************************}
|
***************************************************************************}
|
||||||
@ -3760,7 +3812,8 @@ implementation
|
|||||||
tprocvardef(result).proctypeoption:=proctypeoption;
|
tprocvardef(result).proctypeoption:=proctypeoption;
|
||||||
tprocvardef(result).proccalloption:=proccalloption;
|
tprocvardef(result).proccalloption:=proccalloption;
|
||||||
tprocvardef(result).procoptions:=procoptions;
|
tprocvardef(result).procoptions:=procoptions;
|
||||||
tprocvardef(result).requiredargarea:=requiredargarea;
|
tprocvardef(result).callerargareasize:=callerargareasize;
|
||||||
|
tprocvardef(result).calleeargareasize:=calleeargareasize;
|
||||||
tprocvardef(result).maxparacount:=maxparacount;
|
tprocvardef(result).maxparacount:=maxparacount;
|
||||||
tprocvardef(result).minparacount:=minparacount;
|
tprocvardef(result).minparacount:=minparacount;
|
||||||
for i:=low(tcallercallee) to high(tcallercallee) do
|
for i:=low(tcallercallee) to high(tcallercallee) do
|
||||||
|
|||||||
@ -159,7 +159,8 @@ begin
|
|||||||
On 64bit systems, page zero is 4GB by default, so no problems
|
On 64bit systems, page zero is 4GB by default, so no problems
|
||||||
there.
|
there.
|
||||||
}
|
}
|
||||||
ExeCmd[1]:='ld $PRTOBJ $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -pagezero_size 0x10000 -multiply_defined suppress -L. -o $EXE `cat $RES`';
|
// ExeCmd[1]:='ld $PRTOBJ $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -pagezero_size 0x10000 -multiply_defined suppress -L. -o $EXE `cat $RES`';
|
||||||
|
ExeCmd[1]:='ld $PRTOBJ $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -multiply_defined suppress -L. -o $EXE `cat $RES`';
|
||||||
{$else ndef cpu64bitaddr}
|
{$else ndef cpu64bitaddr}
|
||||||
ExeCmd[1]:='ld $PRTOBJ $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -multiply_defined suppress -L. -o $EXE `cat $RES`';
|
ExeCmd[1]:='ld $PRTOBJ $OPT $DYNLINK $STATIC $GCSECTIONS $STRIP -multiply_defined suppress -L. -o $EXE `cat $RES`';
|
||||||
{$endif ndef cpu64bitaddr}
|
{$endif ndef cpu64bitaddr}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user