* i386 uses now the generic exception management from ncgflw

This commit is contained in:
peter 2002-08-24 18:35:42 +00:00
parent a903647258
commit d551c5d867
2 changed files with 4 additions and 825 deletions

View File

@ -47,7 +47,6 @@ unit cpunode;
n386add,
n386cal,
n386con,
n386flw,
n386mem,
n386set,
n386inl,
@ -61,7 +60,10 @@ unit cpunode;
end.
{
$Log$
Revision 1.17 2002-08-23 16:14:49 peter
Revision 1.18 2002-08-24 18:35:42 peter
* i386 uses now the generic exception management from ncgflw
Revision 1.17 2002/08/23 16:14:49 peter
* tempgen cleanup
* tt_noreuse temp type added that will be used in genentrycode

View File

@ -1,823 +0,0 @@
{
$Id$
Copyright (c) 1998-2002 by Florian Klaempfl
Generate i386 assembler for nodes that influence the flow
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************
}
unit n386flw;
{$i fpcdefs.inc}
interface
uses
node,nflw;
type
ti386raisenode = class(traisenode)
procedure pass_2;override;
end;
ti386tryexceptnode = class(ttryexceptnode)
procedure pass_2;override;
end;
ti386tryfinallynode = class(ttryfinallynode)
procedure pass_2;override;
end;
ti386onnode = class(tonnode)
procedure pass_2;override;
end;
implementation
uses
verbose,systems,
symsym,aasmbase,aasmtai,aasmcpu,
cgbase,pass_2,
cpuinfo,cpubase,paramgr,
nld,ncon,
cga,cgobj,tgobj,rgobj;
{*****************************************************************************
SecondRaise
*****************************************************************************}
procedure ti386raisenode.pass_2;
var
a : tasmlabel;
begin
if assigned(left) then
begin
{ multiple parameters? }
if assigned(right) then
begin
{ push frame }
if assigned(frametree) then
begin
secondpass(frametree);
if codegenerror then
exit;
cg.a_param_loc(exprasmlist,frametree.location,paramanager.getintparaloc(2));
end
else
cg.a_param_const(exprasmlist,OS_INT,0,paramanager.getintparaloc(2));
{ push address }
secondpass(right);
if codegenerror then
exit;
cg.a_param_loc(exprasmlist,right.location,paramanager.getintparaloc(1));
end
else
begin
objectlibrary.getaddrlabel(a);
cg.a_label(exprasmlist,a);
cg.a_param_reg(exprasmlist,OS_INT,R_EBP,paramanager.getintparaloc(2));
emit_sym(A_PUSH,S_L,a);
end;
{ push object }
secondpass(left);
if codegenerror then
exit;
cg.a_param_loc(exprasmlist,left.location,paramanager.getintparaloc(1));
cg.a_call_name(exprasmlist,'FPC_RAISEEXCEPTION');
end
else
begin
cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
cg.a_call_name(exprasmlist,'FPC_RERAISE');
end;
end;
{*****************************************************************************
SecondTryExcept
*****************************************************************************}
var
endexceptlabel : tasmlabel;
{ does the necessary things to clean up the object stack }
{ in the except block }
procedure cleanupobjectstack;
begin
cg.a_call_name(exprasmlist,'FPC_POPOBJECTSTACK');
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
emit_reg(A_PUSH,S_L,R_EAX);
cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
cg.g_maybe_loadself(exprasmlist);
end;
{ pops one element from the exception address stack }
{ and removes the flag }
procedure cleanupaddrstack;
begin
cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
{ allocate eax }
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
emit_reg(A_POP,S_L,R_EAX);
{ deallocate eax }
exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
end;
procedure ti386tryexceptnode.pass_2;
var
exceptlabel,doexceptlabel,oldendexceptlabel,
lastonlabel,
exitexceptlabel,
continueexceptlabel,
breakexceptlabel,
exittrylabel,
continuetrylabel,
breaktrylabel,
doobjectdestroy,
doobjectdestroyandreraise,
oldaktexitlabel,
oldaktexit2label,
oldaktcontinuelabel,
oldaktbreaklabel : tasmlabel;
oldflowcontrol,tryflowcontrol,
exceptflowcontrol : tflowcontrol;
tempbuf,tempaddr : treference;
label
errorexit;
begin
oldflowcontrol:=flowcontrol;
flowcontrol:=[];
{ this can be called recursivly }
oldendexceptlabel:=endexceptlabel;
{ we modify EAX }
include(rg.usedinproc,R_EAX);
{ save the old labels for control flow statements }
oldaktexitlabel:=aktexitlabel;
oldaktexit2label:=aktexit2label;
if assigned(aktbreaklabel) then
begin
oldaktcontinuelabel:=aktcontinuelabel;
oldaktbreaklabel:=aktbreaklabel;
end;
{ get new labels for the control flow statements }
objectlibrary.getlabel(exittrylabel);
objectlibrary.getlabel(exitexceptlabel);
if assigned(aktbreaklabel) then
begin
objectlibrary.getlabel(breaktrylabel);
objectlibrary.getlabel(continuetrylabel);
objectlibrary.getlabel(breakexceptlabel);
objectlibrary.getlabel(continueexceptlabel);
end;
objectlibrary.getlabel(exceptlabel);
objectlibrary.getlabel(doexceptlabel);
objectlibrary.getlabel(endexceptlabel);
objectlibrary.getlabel(lastonlabel);
tg.GetTemp(exprasmlist,JMP_BUF_SIZE,tt_persistant,tempbuf);
tg.GetTemp(exprasmlist,12,tt_persistant,tempaddr);
cg.a_paramaddr_ref(exprasmlist,tempaddr,paramanager.getintparaloc(3));
cg.a_paramaddr_ref(exprasmlist,tempbuf,paramanager.getintparaloc(2));
{ push type of exceptionframe }
cg.a_param_const(exprasmlist,OS_INT,1,paramanager.getintparaloc(1));
cg.a_call_name(exprasmlist,'FPC_PUSHEXCEPTADDR');
{ allocate eax }
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
emit_reg(A_PUSH,S_L,R_EAX);
cg.a_call_name(exprasmlist,'FPC_SETJMP');
emit_reg(A_PUSH,S_L,R_EAX);
emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
{ deallocate eax }
exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
emitjmp(C_NE,exceptlabel);
{ try block }
{ set control flow labels for the try block }
aktexitlabel:=exittrylabel;
aktexit2label:=exittrylabel;
if assigned(oldaktbreaklabel) then
begin
aktcontinuelabel:=continuetrylabel;
aktbreaklabel:=breaktrylabel;
end;
flowcontrol:=[];
secondpass(left);
tryflowcontrol:=flowcontrol;
if codegenerror then
goto errorexit;
cg.a_label(exprasmlist,exceptlabel);
cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
tg.UnGetTemp(exprasmlist,tempaddr);
tg.UnGetTemp(exprasmlist,tempbuf);
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
emit_reg(A_POP,S_L,R_EAX);
emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
emitjmp(C_E,endexceptlabel);
cg.a_label(exprasmlist,doexceptlabel);
{ set control flow labels for the except block }
{ and the on statements }
aktexitlabel:=exitexceptlabel;
aktexit2label:=exitexceptlabel;
if assigned(oldaktbreaklabel) then
begin
aktcontinuelabel:=continueexceptlabel;
aktbreaklabel:=breakexceptlabel;
end;
flowcontrol:=[];
{ on statements }
if assigned(right) then
secondpass(right);
cg.a_label(exprasmlist,lastonlabel);
{ default handling except handling }
if assigned(t1) then
begin
{ FPC_CATCHES must be called with
'default handler' flag (=-1)
}
cg.a_param_const(exprasmlist,OS_INT,aword(-1),paramanager.getintparaloc(1));
cg.a_call_name(exprasmlist,'FPC_CATCHES');
cg.g_maybe_loadself(exprasmlist);
{ the destruction of the exception object must be also }
{ guarded by an exception frame }
objectlibrary.getlabel(doobjectdestroy);
objectlibrary.getlabel(doobjectdestroyandreraise);
tg.GetTemp(exprasmlist,JMP_BUF_SIZE,tt_persistant,tempbuf);
tg.GetTemp(exprasmlist,12,tt_persistant,tempaddr);
cg.a_paramaddr_ref(exprasmlist,tempaddr,paramanager.getintparaloc(3));
cg.a_paramaddr_ref(exprasmlist,tempbuf,paramanager.getintparaloc(2));
{ push type of exceptionframe }
cg.a_param_const(exprasmlist,OS_INT,1,paramanager.getintparaloc(1));
cg.a_call_name(exprasmlist,'FPC_PUSHEXCEPTADDR');
{ allocate eax }
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
emit_reg(A_PUSH,S_L,R_EAX);
cg.a_call_name(exprasmlist,'FPC_SETJMP');
emit_reg(A_PUSH,S_L,R_EAX);
emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
{ deallocate eax }
exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
emitjmp(C_NE,exceptlabel);
{ here we don't have to reset flowcontrol }
{ the default and on flowcontrols are handled equal }
secondpass(t1);
exceptflowcontrol:=flowcontrol;
cg.a_label(exprasmlist,doobjectdestroyandreraise);
cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
tg.Ungettemp(exprasmlist,tempaddr);
tg.Ungettemp(exprasmlist,tempbuf);
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
exprasmList.concat(Taicpu.op_reg(A_POP,S_L,R_EAX));
exprasmList.concat(Taicpu.op_reg_reg(A_TEST,S_L,R_EAX,R_EAX));
exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
emitjmp(C_E,doobjectdestroy);
cg.a_call_name(exprasmlist,'FPC_POPSECONDOBJECTSTACK');
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
emit_reg(A_PUSH,S_L,R_EAX);
cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
{ we don't need to restore esi here because reraise never }
{ returns }
cg.a_call_name(exprasmlist,'FPC_RERAISE');
cg.a_label(exprasmlist,doobjectdestroy);
cleanupobjectstack;
cg.a_jmp_always(exprasmlist,endexceptlabel);
end
else
begin
cg.a_call_name(exprasmlist,'FPC_RERAISE');
exceptflowcontrol:=flowcontrol;
end;
if fc_exit in exceptflowcontrol then
begin
{ do some magic for exit in the try block }
cg.a_label(exprasmlist,exitexceptlabel);
{ we must also destroy the address frame which guards }
{ exception object }
cleanupaddrstack;
cleanupobjectstack;
cg.a_jmp_always(exprasmlist,oldaktexitlabel);
end;
if fc_break in exceptflowcontrol then
begin
cg.a_label(exprasmlist,breakexceptlabel);
{ we must also destroy the address frame which guards }
{ exception object }
cleanupaddrstack;
cleanupobjectstack;
cg.a_jmp_always(exprasmlist,oldaktbreaklabel);
end;
if fc_continue in exceptflowcontrol then
begin
cg.a_label(exprasmlist,continueexceptlabel);
{ we must also destroy the address frame which guards }
{ exception object }
cleanupaddrstack;
cleanupobjectstack;
cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
end;
if fc_exit in tryflowcontrol then
begin
{ do some magic for exit in the try block }
cg.a_label(exprasmlist,exittrylabel);
cleanupaddrstack;
cg.a_jmp_always(exprasmlist,oldaktexitlabel);
end;
if fc_break in tryflowcontrol then
begin
cg.a_label(exprasmlist,breaktrylabel);
cleanupaddrstack;
cg.a_jmp_always(exprasmlist,oldaktbreaklabel);
end;
if fc_continue in tryflowcontrol then
begin
cg.a_label(exprasmlist,continuetrylabel);
cleanupaddrstack;
cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
end;
cg.a_label(exprasmlist,endexceptlabel);
errorexit:
{ restore all saved labels }
endexceptlabel:=oldendexceptlabel;
{ restore the control flow labels }
aktexitlabel:=oldaktexitlabel;
aktexit2label:=oldaktexit2label;
if assigned(oldaktbreaklabel) then
begin
aktcontinuelabel:=oldaktcontinuelabel;
aktbreaklabel:=oldaktbreaklabel;
end;
{ return all used control flow statements }
flowcontrol:=oldflowcontrol+exceptflowcontrol+
tryflowcontrol;
end;
procedure ti386onnode.pass_2;
var
nextonlabel,
exitonlabel,
continueonlabel,
breakonlabel,
oldaktexitlabel,
oldaktexit2label,
oldaktcontinuelabel,
doobjectdestroyandreraise,
doobjectdestroy,
oldaktbreaklabel : tasmlabel;
ref : treference;
oldflowcontrol : tflowcontrol;
tempbuf,tempaddr : treference;
begin
oldflowcontrol:=flowcontrol;
flowcontrol:=[];
objectlibrary.getlabel(nextonlabel);
{ push the vmt }
emit_sym(A_PUSH,S_L,
objectlibrary.newasmsymbol(excepttype.vmt_mangledname));
cg.a_call_name(exprasmlist,'FPC_CATCHES');
{ allocate eax }
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
emitjmp(C_E,nextonlabel);
ref.symbol:=nil;
tg.GetTemp(exprasmlist,4,tt_normal,ref);
{ what a hack ! }
if assigned(exceptsymtable) then
tvarsym(exceptsymtable.symindex.first).address:=ref.offset;
emit_reg_ref(A_MOV,S_L,R_EAX,ref);
{ deallocate eax }
exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
{ in the case that another exception is risen }
{ we've to destroy the old one }
objectlibrary.getlabel(doobjectdestroyandreraise);
tg.GetTemp(exprasmlist,12,tt_persistant,tempaddr);
tg.GetTemp(exprasmlist,JMP_BUF_SIZE,tt_persistant,tempbuf);
cg.a_paramaddr_ref(exprasmlist,tempaddr,paramanager.getintparaloc(3));
cg.a_paramaddr_ref(exprasmlist,tempbuf,paramanager.getintparaloc(2));
cg.a_param_const(exprasmlist,OS_INT,1,paramanager.getintparaloc(1));
cg.a_call_name(exprasmlist,'FPC_PUSHEXCEPTADDR');
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
exprasmList.concat(Taicpu.op_reg(A_PUSH,S_L,R_EAX));
exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
cg.a_call_name(exprasmlist,'FPC_SETJMP');
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
exprasmList.concat(Taicpu.op_reg(A_PUSH,S_L,R_EAX));
exprasmList.concat(Taicpu.op_reg_reg(A_TEST,S_L,R_EAX,R_EAX));
exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
emitjmp(C_NE,doobjectdestroyandreraise);
if assigned(right) then
begin
oldaktexitlabel:=aktexitlabel;
oldaktexit2label:=aktexit2label;
objectlibrary.getlabel(exitonlabel);
aktexitlabel:=exitonlabel;
aktexit2label:=exitonlabel;
if assigned(aktbreaklabel) then
begin
oldaktcontinuelabel:=aktcontinuelabel;
oldaktbreaklabel:=aktbreaklabel;
objectlibrary.getlabel(breakonlabel);
objectlibrary.getlabel(continueonlabel);
aktcontinuelabel:=continueonlabel;
aktbreaklabel:=breakonlabel;
end;
{ esi is destroyed by FPC_CATCHES }
cg.g_maybe_loadself(exprasmlist);
secondpass(right);
end;
objectlibrary.getlabel(doobjectdestroy);
cg.a_label(exprasmlist,doobjectdestroyandreraise);
cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
tg.Ungettemp(exprasmlist,tempaddr);
tg.Ungettemp(exprasmlist,tempbuf);
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
exprasmList.concat(Taicpu.op_reg(A_POP,S_L,R_EAX));
exprasmList.concat(Taicpu.op_reg_reg(A_TEST,S_L,R_EAX,R_EAX));
exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
emitjmp(C_E,doobjectdestroy);
cg.a_call_name(exprasmlist,'FPC_POPSECONDOBJECTSTACK');
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
emit_reg(A_PUSH,S_L,R_EAX);
cg.a_call_name(exprasmlist,'FPC_DESTROYEXCEPTION');
exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
{ we don't need to restore esi here because reraise never }
{ returns }
cg.a_call_name(exprasmlist,'FPC_RERAISE');
cg.a_label(exprasmlist,doobjectdestroy);
cleanupobjectstack;
{ clear some stuff }
tg.ungetiftemp(exprasmlist,ref);
cg.a_jmp_always(exprasmlist,endexceptlabel);
if assigned(right) then
begin
{ special handling for control flow instructions }
if fc_exit in flowcontrol then
begin
{ the address and object pop does secondtryexcept }
cg.a_label(exprasmlist,exitonlabel);
cg.a_jmp_always(exprasmlist,oldaktexitlabel);
end;
if fc_break in flowcontrol then
begin
{ the address and object pop does secondtryexcept }
cg.a_label(exprasmlist,breakonlabel);
cg.a_jmp_always(exprasmlist,oldaktbreaklabel);
end;
if fc_continue in flowcontrol then
begin
{ the address and object pop does secondtryexcept }
cg.a_label(exprasmlist,continueonlabel);
cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
end;
aktexitlabel:=oldaktexitlabel;
aktexit2label:=oldaktexit2label;
if assigned(oldaktbreaklabel) then
begin
aktcontinuelabel:=oldaktcontinuelabel;
aktbreaklabel:=oldaktbreaklabel;
end;
end;
cg.a_label(exprasmlist,nextonlabel);
flowcontrol:=oldflowcontrol+flowcontrol;
{ next on node }
if assigned(left) then
begin
rg.cleartempgen;
secondpass(left);
end;
end;
{*****************************************************************************
SecondTryFinally
*****************************************************************************}
procedure ti386tryfinallynode.pass_2;
var
reraiselabel,
finallylabel,
endfinallylabel,
exitfinallylabel,
continuefinallylabel,
breakfinallylabel,
oldaktexitlabel,
oldaktexit2label,
oldaktcontinuelabel,
oldaktbreaklabel : tasmlabel;
oldflowcontrol,tryflowcontrol : tflowcontrol;
decconst : longint;
tempbuf,tempaddr : treference;
begin
{ check if child nodes do a break/continue/exit }
oldflowcontrol:=flowcontrol;
flowcontrol:=[];
{ we modify EAX }
include(rg.usedinproc,R_EAX);
objectlibrary.getlabel(finallylabel);
objectlibrary.getlabel(endfinallylabel);
objectlibrary.getlabel(reraiselabel);
{ the finally block must catch break, continue and exit }
{ statements }
oldaktexitlabel:=aktexitlabel;
oldaktexit2label:=aktexit2label;
objectlibrary.getlabel(exitfinallylabel);
aktexitlabel:=exitfinallylabel;
aktexit2label:=exitfinallylabel;
if assigned(aktbreaklabel) then
begin
oldaktcontinuelabel:=aktcontinuelabel;
oldaktbreaklabel:=aktbreaklabel;
objectlibrary.getlabel(breakfinallylabel);
objectlibrary.getlabel(continuefinallylabel);
aktcontinuelabel:=continuefinallylabel;
aktbreaklabel:=breakfinallylabel;
end;
tg.Gettemp(exprasmlist,12,tt_persistant,tempaddr);
tg.Gettemp(exprasmlist,JMP_BUF_SIZE,tt_persistant,tempbuf);
cg.a_paramaddr_ref(exprasmlist,tempaddr,paramanager.getintparaloc(3));
cg.a_paramaddr_ref(exprasmlist,tempbuf,paramanager.getintparaloc(2));
{ Type of stack-frame must be pushed}
cg.a_param_const(exprasmlist,OS_INT,1,paramanager.getintparaloc(1));
cg.a_call_name(exprasmlist,'FPC_PUSHEXCEPTADDR');
{ allocate eax }
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
emit_reg(A_PUSH,S_L,R_EAX);
cg.a_call_name(exprasmlist,'FPC_SETJMP');
emit_reg(A_PUSH,S_L,R_EAX);
emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
{ deallocate eax }
exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
emitjmp(C_NE,finallylabel);
{ try code }
if assigned(left) then
begin
secondpass(left);
tryflowcontrol:=flowcontrol;
if codegenerror then
exit;
end;
cg.a_label(exprasmlist,finallylabel);
cg.a_call_name(exprasmlist,'FPC_POPADDRSTACK');
tg.Ungettemp(exprasmlist,tempaddr);
tg.Ungettemp(exprasmlist,tempbuf);
{ finally code }
flowcontrol:=[];
secondpass(right);
if flowcontrol<>[] then
CGMessage(cg_e_control_flow_outside_finally);
if codegenerror then
exit;
{ allocate eax }
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
emit_reg(A_POP,S_L,R_EAX);
emit_reg_reg(A_TEST,S_L,R_EAX,R_EAX);
emitjmp(C_E,endfinallylabel);
emit_reg(A_DEC,S_L,R_EAX);
emitjmp(C_Z,reraiselabel);
if fc_exit in tryflowcontrol then
begin
emit_reg(A_DEC,S_L,R_EAX);
emitjmp(C_Z,oldaktexitlabel);
decconst:=1;
end
else
decconst:=2;
if fc_break in tryflowcontrol then
begin
emit_const_reg(A_SUB,S_L,decconst,R_EAX);
emitjmp(C_Z,oldaktbreaklabel);
decconst:=1;
end
else
inc(decconst);
if fc_continue in tryflowcontrol then
begin
emit_const_reg(A_SUB,S_L,decconst,R_EAX);
emitjmp(C_Z,oldaktcontinuelabel);
end;
{ deallocate eax }
exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
cg.a_label(exprasmlist,reraiselabel);
cg.a_call_name(exprasmlist,'FPC_RERAISE');
{ do some magic for exit,break,continue in the try block }
if fc_exit in tryflowcontrol then
begin
cg.a_label(exprasmlist,exitfinallylabel);
{ allocate eax }
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
emit_reg(A_POP,S_L,R_EAX);
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
emit_const(A_PUSH,S_L,2);
cg.a_jmp_always(exprasmlist,finallylabel);
end;
if fc_break in tryflowcontrol then
begin
cg.a_label(exprasmlist,breakfinallylabel);
{ allocate eax }
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
emit_reg(A_POP,S_L,R_EAX);
{ deallocate eax }
exprasmList.concat(tai_regalloc.DeAlloc(R_EAX));
emit_const(A_PUSH,S_L,3);
cg.a_jmp_always(exprasmlist,finallylabel);
end;
if fc_continue in tryflowcontrol then
begin
cg.a_label(exprasmlist,continuefinallylabel);
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
emit_reg(A_POP,S_L,R_EAX);
exprasmList.concat(tai_regalloc.Alloc(R_EAX));
emit_const(A_PUSH,S_L,4);
cg.a_jmp_always(exprasmlist,finallylabel);
end;
cg.a_label(exprasmlist,endfinallylabel);
aktexitlabel:=oldaktexitlabel;
aktexit2label:=oldaktexit2label;
if assigned(aktbreaklabel) then
begin
aktcontinuelabel:=oldaktcontinuelabel;
aktbreaklabel:=oldaktbreaklabel;
end;
flowcontrol:=oldflowcontrol+tryflowcontrol;
end;
begin
craisenode:=ti386raisenode;
ctryexceptnode:=ti386tryexceptnode;
ctryfinallynode:=ti386tryfinallynode;
connode:=ti386onnode;
end.
{
$Log$
Revision 1.34 2002-08-23 16:14:49 peter
* tempgen cleanup
* tt_noreuse temp type added that will be used in genentrycode
Revision 1.33 2002/08/15 15:15:55 carl
* jmpbuf size allocation for exceptions is now cpu specific (as it should)
* more generic nodes for maths
* several fixes for better m68k support
Revision 1.32 2002/08/11 14:32:30 peter
* renamed current_library to objectlibrary
Revision 1.31 2002/08/11 13:24:17 peter
* saving of asmsymbols in ppu supported
* asmsymbollist global is removed and moved into a new class
tasmlibrarydata that will hold the info of a .a file which
corresponds with a single module. Added librarydata to tmodule
to keep the library info stored for the module. In the future the
objectfiles will also be stored to the tasmlibrarydata class
* all getlabel/newasmsymbol and friends are moved to the new class
Revision 1.30 2002/07/11 14:41:33 florian
* start of the new generic parameter handling
Revision 1.29 2002/07/07 09:52:34 florian
* powerpc target fixed, very simple units can be compiled
* some basic stuff for better callparanode handling, far from being finished
Revision 1.28 2002/07/01 18:46:33 peter
* internal linker
* reorganized aasm layer
Revision 1.27 2002/05/20 13:30:41 carl
* bugfix of hdisponen (base must be set, not index)
* more portability fixes
Revision 1.26 2002/05/18 13:34:25 peter
* readded missing revisions
Revision 1.25 2002/05/16 19:46:51 carl
+ defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
+ try to fix temp allocation (still in ifdef)
+ generic constructor calls
+ start of tassembler / tmodulebase class cleanup
Revision 1.23 2002/05/12 16:53:17 peter
* moved entry and exitcode to ncgutil and cgobj
* foreach gets extra argument for passing local data to the
iterator function
* -CR checks also class typecasts at runtime by changing them
into as
* fixed compiler to cycle with the -CR option
* fixed stabs with elf writer, finally the global variables can
be watched
* removed a lot of routines from cga unit and replaced them by
calls to cgobj
* u32bit-s32bit updates for and,or,xor nodes. When one element is
u32bit then the other is typecasted also to u32bit without giving
a rangecheck warning/error.
* fixed pascal calling method with reversing also the high tree in
the parast, detected by tcalcst3 test
Revision 1.22 2002/04/04 19:06:11 peter
* removed unused units
* use tlocation.size in cg.a_*loc*() routines
Revision 1.21 2002/04/02 17:11:36 peter
* tlocation,treference update
* LOC_CONSTANT added for better constant handling
* secondadd splitted in multiple routines
* location_force_reg added for loading a location to a register
of a specified size
* secondassignment parses now first the right and then the left node
(this is compatible with Kylix). This saves a lot of push/pop especially
with string operations
* adapted some routines to use the new cg methods
Revision 1.20 2002/03/31 20:26:38 jonas
+ a_loadfpu_* and a_loadmm_* methods in tcg
* register allocation is now handled by a class and is mostly processor
independent (+rgobj.pas and i386/rgcpu.pas)
* temp allocation is now handled by a class (+tgobj.pas, -i386\tgcpu.pas)
* some small improvements and fixes to the optimizer
* some register allocation fixes
* some fpuvaroffset fixes in the unary minus node
* push/popusedregisters is now called rg.save/restoreusedregisters and
(for i386) uses temps instead of push/pop's when using -Op3 (that code is
also better optimizable)
* fixed and optimized register saving/restoring for new/dispose nodes
* LOC_FPU locations now also require their "register" field to be set to
R_ST, not R_ST0 (the latter is used for LOC_CFPUREGISTER locations only)
- list field removed of the tnode class because it's not used currently
and can cause hard-to-find bugs
}