mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-21 16:09:26 +02:00
* i386 uses now the generic exception management from ncgflw
This commit is contained in:
parent
a903647258
commit
d551c5d867
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user