+ no stackframe is generated for i386 if possible

git-svn-id: trunk@2162 -
This commit is contained in:
florian 2006-01-04 19:19:06 +00:00
parent a85bb43749
commit f7d2c47f73
5 changed files with 94 additions and 5 deletions

View File

@ -240,7 +240,9 @@ than 255 characters. That's why using Ansi Strings}
pi_needs_got, pi_needs_got,
{ references var/proc/type/const in static symtable, { references var/proc/type/const in static symtable,
i.e. not allowed for inlining from other units } i.e. not allowed for inlining from other units }
pi_uses_static_symtable pi_uses_static_symtable,
{ set if the procedure has to push parameters onto the stack }
pi_has_stackparameter
); );
tprocinfoflags=set of tprocinfoflag; tprocinfoflags=set of tprocinfoflag;

View File

@ -264,7 +264,7 @@ unit cgcpu;
end end
else else
list.concat(Taicpu.op_none(A_LEAVE,S_NO)); list.concat(Taicpu.op_none(A_LEAVE,S_NO));
list.concat(tai_regalloc.dealloc(NR_FRAME_POINTER_REG,nil)); list.concat(tai_regalloc.dealloc(current_procinfo.framepointer,nil));
end; end;
{ return from proc } { return from proc }

View File

@ -130,6 +130,9 @@ interface
procedure printnodedata(var t:text);override; procedure printnodedata(var t:text);override;
function para_count:longint; function para_count:longint;
function get_load_methodpointer:tnode; function get_load_methodpointer:tnode;
{ checks if there are any parameters which end up at the stack, i.e.
which have LOC_REFERENCE and set pi_has_stackparameter if this applies }
procedure check_stack_parameters;
private private
AbstractMethodsList : TStringList; AbstractMethodsList : TStringList;
end; end;
@ -2333,6 +2336,22 @@ type
end; end;
procedure tcallnode.check_stack_parameters;
var
hp : tcallparanode;
begin
hp:=tcallparanode(left);
while assigned(hp) do
begin
if assigned(hp.parasym) and
assigned(hp.parasym.paraloc[callerside].location) and
(hp.parasym.paraloc[callerside].location^.loc=LOC_REFERENCE) then
include(current_procinfo.flags,pi_has_stackparameter);
hp:=tcallparanode(hp.right);
end;
end;
function tcallnode.pass_1 : tnode; function tcallnode.pass_1 : tnode;
var var
st : tsymtable; st : tsymtable;
@ -2378,7 +2397,16 @@ type
{ work trough all parameters to get the register requirements } { work trough all parameters to get the register requirements }
if assigned(left) then if assigned(left) then
tcallparanode(left).det_registers; begin
tcallparanode(left).det_registers;
if cs_optimize in aktglobalswitches then
begin
{ check for stacked parameters }
check_stack_parameters;
end;
end;
{ order parameters } { order parameters }
order_parameters; order_parameters;

View File

@ -54,6 +54,8 @@ interface
procedure add_to_symtablestack; procedure add_to_symtablestack;
procedure remove_from_symtablestack; procedure remove_from_symtablestack;
procedure parse_body; procedure parse_body;
function stack_tainting_parameter : boolean;
end; end;
@ -96,7 +98,7 @@ implementation
scanner,import,gendef, scanner,import,gendef,
pbase,pstatmnt,pdecl,pdecsub,pexports, pbase,pstatmnt,pdecl,pdecsub,pexports,
{ codegen } { codegen }
tgobj,cgobj,dbgbase, tgobj,cgbase,cgobj,dbgbase,
ncgutil,regvars ncgutil,regvars
{$if defined(arm) or defined(powerpc) or defined(powerpc64)} {$if defined(arm) or defined(powerpc) or defined(powerpc64)}
,aasmcpu ,aasmcpu
@ -604,6 +606,29 @@ implementation
end; end;
procedure check_for_stack(p : tnamedindexitem;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).vartype.def) or
is_array_of_const(tparavarsym(p).vartype.def) 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.foreach_static(@check_for_stack,@result);
end;
procedure tcgprocinfo.generate_code; procedure tcgprocinfo.generate_code;
var var
oldprocinfo : tprocinfo; oldprocinfo : tprocinfo;
@ -680,6 +705,38 @@ implementation
{ set the start offset to the start of the temp area in the stack } { set the start offset to the start of the temp area in the stack }
tg:=ttgobj.create; tg:=ttgobj.create;
{$ifdef i386}
{ try to strip the stack frame }
{ set the framepointer to esp if:
- no assembler directive, those are handled elsewhere
- no exceptions are used
- no debug info
- no pushes are used/esp modifications, could be:
* outgoing parameters on the stack
* incoming parameters on the stack
* open arrays
- no inline assembler
}
if (cs_optimize in aktglobalswitches) and
not(po_assembler in procdef.procoptions) and
((flags*[pi_has_assembler_block,pi_uses_exceptions,pi_is_assembler,
pi_needs_implicit_finally,pi_has_implicit_finally,pi_has_stackparameter])=[]) then
begin
{ we need the parameter info here to determine if the procedure gets
parameters on the stack
calling generate_parameter_info doesn't hurt but it costs time
}
generate_parameter_info;
if not(stack_tainting_parameter) then
begin
{ Only need to set the framepointer }
framepointer:=NR_STACK_POINTER_REG;
tg.direction:=1;
end;
end;
{$endif i386}
{ Create register allocator } { Create register allocator }
cg.init_register_allocators; cg.init_register_allocators;
@ -713,6 +770,7 @@ implementation
procdef.has_paraloc_info:=true; procdef.has_paraloc_info:=true;
end; end;
{ generate code for the node tree } { generate code for the node tree }
do_secondpass(code); do_secondpass(code);
aktproccode.concatlist(exprasmlist); aktproccode.concatlist(exprasmlist);

View File

@ -1839,11 +1839,12 @@ unit cgx86;
{ save old framepointer } { save old framepointer }
if not nostackframe then if not nostackframe then
begin begin
list.concat(tai_regalloc.alloc(current_procinfo.framepointer,nil));
if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then if (current_procinfo.framepointer=NR_STACK_POINTER_REG) then
CGmessage(cg_d_stackframe_omited) CGmessage(cg_d_stackframe_omited)
else else
begin begin
list.concat(tai_regalloc.alloc(NR_FRAME_POINTER_REG,nil));
include(rg[R_INTREGISTER].preserved_by_proc,RS_FRAME_POINTER_REG); include(rg[R_INTREGISTER].preserved_by_proc,RS_FRAME_POINTER_REG);
list.concat(Taicpu.op_reg(A_PUSH,tcgsize2opsize[OS_ADDR],NR_FRAME_POINTER_REG)); list.concat(Taicpu.op_reg(A_PUSH,tcgsize2opsize[OS_ADDR],NR_FRAME_POINTER_REG));
{ Return address and FP are both on stack } { Return address and FP are both on stack }