mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-10-01 17:21:43 +02:00
* stack allocation is now done separately (at the end) of genentrycode
so temps. can be allocated before. * fix generic exception handling
This commit is contained in:
parent
1ef442f4bf
commit
947142291c
@ -27,7 +27,7 @@ unit ncgutil;
|
||||
interface
|
||||
|
||||
uses
|
||||
node,
|
||||
node,cpuinfo,
|
||||
cpubase,cpupara,
|
||||
aasmbase,aasmtai,aasmcpu,
|
||||
cginfo,
|
||||
@ -64,6 +64,27 @@ interface
|
||||
procedure genexitcode(list : TAAsmoutput;parasize:longint;nostackframe,inlined:boolean);
|
||||
procedure genimplicitunitinit(list : TAAsmoutput);
|
||||
procedure genimplicitunitfinal(list : TAAsmoutput);
|
||||
|
||||
{#
|
||||
Allocate the buffers for exception management and setjmp environment.
|
||||
Return a pointer to these buffers, send them to the utility routine
|
||||
so they are registered, and then call setjmp.
|
||||
|
||||
Then compare the result of setjmp with 0, and if not equal
|
||||
to zero, then jump to exceptlabel.
|
||||
|
||||
Also store the result of setjmp to a temporary space by calling g_save_exception_reason
|
||||
|
||||
It is to note that this routine may be called *after* the stackframe of a
|
||||
routine has been called, therefore on machines where the stack cannot
|
||||
be modified, all temps should be allocated on the heap instead of the
|
||||
stack.
|
||||
}
|
||||
procedure new_exception(list : taasmoutput;const jmpbuf,envbuf, href : treference;
|
||||
a : aword; exceptlabel : tasmlabel);
|
||||
procedure free_exception(list : taasmoutput;const jmpbuf, envbuf, href : treference;
|
||||
a : aword ; endexceptlabel : tasmlabel; onlyfree : boolean);
|
||||
|
||||
|
||||
|
||||
implementation
|
||||
@ -82,7 +103,7 @@ implementation
|
||||
gdb,
|
||||
{$endif GDB}
|
||||
ncon,
|
||||
tgobj,cpuinfo,cgobj,cgcpu,cg64f32;
|
||||
tgobj,cgobj,cgcpu,cg64f32;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
@ -207,6 +228,39 @@ implementation
|
||||
end;
|
||||
end;
|
||||
|
||||
{*****************************************************************************
|
||||
EXCEPTION MANAGEMENT
|
||||
*****************************************************************************}
|
||||
|
||||
procedure new_exception(list : taasmoutput;const jmpbuf,envbuf, href : treference;
|
||||
a : aword; exceptlabel : tasmlabel);
|
||||
begin
|
||||
cg.a_paramaddr_ref(list,envbuf,paramanager.getintparaloc(3));
|
||||
cg.a_paramaddr_ref(list,jmpbuf,paramanager.getintparaloc(2));
|
||||
{ push type of exceptionframe }
|
||||
cg.a_param_const(list,OS_S32,1,paramanager.getintparaloc(1));
|
||||
cg.a_call_name(list,'FPC_PUSHEXCEPTADDR');
|
||||
|
||||
cg.a_param_reg(list,OS_ADDR,accumulator,paramanager.getintparaloc(1));
|
||||
cg.a_call_name(list,'FPC_SETJMP');
|
||||
|
||||
cg.g_exception_reason_save(list, href);
|
||||
cg.a_cmp_const_reg_label(list,OS_S32,OC_NE,0,accumulator,exceptlabel);
|
||||
end;
|
||||
|
||||
|
||||
procedure free_exception(list : taasmoutput;const jmpbuf, envbuf, href : treference;
|
||||
a : aword ; endexceptlabel : tasmlabel; onlyfree : boolean);
|
||||
begin
|
||||
cg.a_call_name(list,'FPC_POPADDRSTACK');
|
||||
|
||||
if not onlyfree then
|
||||
begin
|
||||
cg.g_exception_reason_load(list, href);
|
||||
cg.a_cmp_const_reg_label(list,OS_S32,OC_EQ,a,accumulator,endexceptlabel);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
{*****************************************************************************
|
||||
TLocation
|
||||
@ -1082,83 +1136,18 @@ implementation
|
||||
href : treference;
|
||||
p : tsymtable;
|
||||
tmpreg : tregister;
|
||||
stackalloclist : taasmoutput;
|
||||
begin
|
||||
{ Insert alignment and assembler names }
|
||||
if not inlined then
|
||||
begin
|
||||
{ Align, gprof uses 16 byte granularity }
|
||||
if (cs_profile in aktmoduleswitches) then
|
||||
list.concat(Tai_align.Create_op(16,$90))
|
||||
else
|
||||
list.concat(Tai_align.Create(aktalignment.procalign));
|
||||
|
||||
if (cs_profile in aktmoduleswitches) or
|
||||
(aktprocdef.owner.symtabletype=globalsymtable) or
|
||||
(assigned(procinfo^._class) and (procinfo^._class.owner.symtabletype=globalsymtable)) then
|
||||
make_global:=true;
|
||||
|
||||
if make_global or ((procinfo^.flags and pi_is_global) <> 0) then
|
||||
aktprocsym.is_global := True;
|
||||
|
||||
{$ifdef GDB}
|
||||
if (cs_debuginfo in aktmoduleswitches) then
|
||||
begin
|
||||
aktprocdef.concatstabto(list);
|
||||
aktprocsym.isstabwritten:=true;
|
||||
end;
|
||||
{$endif GDB}
|
||||
|
||||
repeat
|
||||
hs:=aktprocdef.aliasnames.getfirst;
|
||||
if hs='' then
|
||||
break;
|
||||
{$ifdef GDB}
|
||||
if (cs_debuginfo in aktmoduleswitches) and
|
||||
target_info.use_function_relative_addresses then
|
||||
list.concat(Tai_stab_function_name.Create(strpnew(hs)));
|
||||
{$endif GDB}
|
||||
if make_global then
|
||||
list.concat(Tai_symbol.Createname_global(hs,0))
|
||||
else
|
||||
list.concat(Tai_symbol.Createname(hs,0));
|
||||
until false;
|
||||
|
||||
{$ifdef i386}
|
||||
{ at least for the ppc this applies always, so this code isn't usable (FK) }
|
||||
{ omit stack frame ? }
|
||||
if (procinfo^.framepointer=STACK_POINTER_REG) then
|
||||
begin
|
||||
CGMessage(cg_d_stackframe_omited);
|
||||
nostackframe:=true;
|
||||
if (aktprocdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
|
||||
parasize:=0
|
||||
else
|
||||
parasize:=aktprocdef.parast.datasize+procinfo^.para_offset-4;
|
||||
if stackframe<>0 then
|
||||
cg.a_op_const_reg(list,OP_SUB,stackframe,procinfo^.framepointer);
|
||||
end
|
||||
else
|
||||
{$endif i386}
|
||||
begin
|
||||
nostackframe:=false;
|
||||
if (aktprocdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
|
||||
parasize:=0
|
||||
else
|
||||
parasize:=aktprocdef.parast.datasize+procinfo^.para_offset-target_info.first_parm_offset;
|
||||
|
||||
if (po_interrupt in aktprocdef.procoptions) then
|
||||
cg.g_interrupt_stackframe_entry(list);
|
||||
|
||||
cg.g_stackframe_entry(list,stackframe);
|
||||
|
||||
if (cs_check_stack in aktlocalswitches) then
|
||||
cg.g_stackcheck(list,stackframe);
|
||||
end;
|
||||
|
||||
if (cs_profile in aktmoduleswitches) and
|
||||
not(po_assembler in aktprocdef.procoptions) then
|
||||
stackalloclist:=taasmoutput.Create;
|
||||
|
||||
{ the actual stack allocation code, symbol entry point and
|
||||
gdb stabs information is generated AFTER the rest of this
|
||||
code, since temp. allocation might occur before - carl
|
||||
}
|
||||
|
||||
if (cs_profile in aktmoduleswitches) and
|
||||
not(po_assembler in aktprocdef.procoptions) and not(inlined) then
|
||||
cg.g_profilecode(list);
|
||||
end;
|
||||
|
||||
{ for the save all registers we can simply use a pusha,popa which
|
||||
push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
|
||||
@ -1258,7 +1247,10 @@ implementation
|
||||
not(aktprocdef.proctypeoption in [potype_unitfinalize,potype_unitinit]) then
|
||||
begin
|
||||
include(rg.usedinproc,accumulator);
|
||||
cg.g_new_exception(list,procinfo^.exception_jmp_ref,
|
||||
tg.gettempofsizereferencepersistant(list,24,procinfo^.exception_jmp_ref);
|
||||
tg.gettempofsizereferencepersistant(list,12,procinfo^.exception_env_ref);
|
||||
tg.gettempofsizereferencepersistant(list,sizeof(aword),procinfo^.exception_result_ref);
|
||||
new_exception(list,procinfo^.exception_jmp_ref,
|
||||
procinfo^.exception_env_ref,
|
||||
procinfo^.exception_result_ref,1,aktexitlabel);
|
||||
{ probably we've to reload self here }
|
||||
@ -1273,6 +1265,86 @@ implementation
|
||||
|
||||
if inlined then
|
||||
load_regvars(list,nil);
|
||||
|
||||
{************************* Stack allocation **************************}
|
||||
{ and symbol entry point as well as debug information }
|
||||
{ will be inserted in front of the rest of this list. }
|
||||
{ Insert alignment and assembler names }
|
||||
if not inlined then
|
||||
begin
|
||||
{ Align, gprof uses 16 byte granularity }
|
||||
if (cs_profile in aktmoduleswitches) then
|
||||
stackalloclist.concat(Tai_align.Create_op(16,$90))
|
||||
else
|
||||
stackalloclist.concat(Tai_align.Create(aktalignment.procalign));
|
||||
|
||||
if (cs_profile in aktmoduleswitches) or
|
||||
(aktprocdef.owner.symtabletype=globalsymtable) or
|
||||
(assigned(procinfo^._class) and (procinfo^._class.owner.symtabletype=globalsymtable)) then
|
||||
make_global:=true;
|
||||
|
||||
if make_global or ((procinfo^.flags and pi_is_global) <> 0) then
|
||||
aktprocsym.is_global := True;
|
||||
|
||||
{$ifdef GDB}
|
||||
if (cs_debuginfo in aktmoduleswitches) then
|
||||
begin
|
||||
aktprocdef.concatstabto(stackalloclist);
|
||||
aktprocsym.isstabwritten:=true;
|
||||
end;
|
||||
{$endif GDB}
|
||||
|
||||
repeat
|
||||
hs:=aktprocdef.aliasnames.getfirst;
|
||||
if hs='' then
|
||||
break;
|
||||
{$ifdef GDB}
|
||||
if (cs_debuginfo in aktmoduleswitches) and
|
||||
target_info.use_function_relative_addresses then
|
||||
stackalloclist.concat(Tai_stab_function_name.Create(strpnew(hs)));
|
||||
{$endif GDB}
|
||||
if make_global then
|
||||
stackalloclist.concat(Tai_symbol.Createname_global(hs,0))
|
||||
else
|
||||
stackalloclist.concat(Tai_symbol.Createname(hs,0));
|
||||
until false;
|
||||
|
||||
stackframe:=stackframe+tg.gettempsize;
|
||||
{$ifndef powerpc}
|
||||
{ at least for the ppc this applies always, so this code isn't usable (FK) }
|
||||
{ omit stack frame ? }
|
||||
if (procinfo^.framepointer=STACK_POINTER_REG) then
|
||||
begin
|
||||
CGMessage(cg_d_stackframe_omited);
|
||||
nostackframe:=true;
|
||||
if (aktprocdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
|
||||
parasize:=0
|
||||
else
|
||||
parasize:=aktprocdef.parast.datasize+procinfo^.para_offset-4;
|
||||
if stackframe<>0 then
|
||||
cg.a_op_const_reg(stackalloclist,OP_SUB,stackframe,procinfo^.framepointer);
|
||||
end
|
||||
else
|
||||
{$endif powerpc}
|
||||
begin
|
||||
nostackframe:=false;
|
||||
if (aktprocdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
|
||||
parasize:=0
|
||||
else
|
||||
parasize:=aktprocdef.parast.datasize+procinfo^.para_offset-target_info.first_parm_offset;
|
||||
|
||||
if (po_interrupt in aktprocdef.procoptions) then
|
||||
cg.g_interrupt_stackframe_entry(stackalloclist);
|
||||
|
||||
cg.g_stackframe_entry(stackalloclist,stackframe);
|
||||
|
||||
if (cs_check_stack in aktlocalswitches) then
|
||||
cg.g_stackcheck(stackalloclist,stackframe);
|
||||
end;
|
||||
list.insertlist(stackalloclist);
|
||||
{ stackalloclist.free;}
|
||||
end;
|
||||
{************************* End Stack allocation **************************}
|
||||
end;
|
||||
|
||||
|
||||
@ -1342,7 +1414,7 @@ implementation
|
||||
{ the exception helper routines modify all registers }
|
||||
aktprocdef.usedregisters:=all_registers;
|
||||
getlabel(noreraiselabel);
|
||||
cg.g_free_exception(list,
|
||||
free_exception(list,
|
||||
procinfo^.exception_jmp_ref,
|
||||
procinfo^.exception_env_ref,
|
||||
procinfo^.exception_result_ref,0
|
||||
@ -1629,7 +1701,12 @@ implementation
|
||||
end.
|
||||
{
|
||||
$Log$
|
||||
Revision 1.30 2002-08-06 20:55:21 florian
|
||||
Revision 1.31 2002-08-09 19:16:57 carl
|
||||
* stack allocation is now done separately (at the end) of genentrycode
|
||||
so temps. can be allocated before.
|
||||
* fix generic exception handling
|
||||
|
||||
Revision 1.30 2002/08/06 20:55:21 florian
|
||||
* first part of ppc calling conventions fix
|
||||
|
||||
Revision 1.29 2002/08/04 19:09:22 carl
|
||||
|
Loading…
Reference in New Issue
Block a user