mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-17 11:45:32 +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,
|
n386add,
|
||||||
n386cal,
|
n386cal,
|
||||||
n386con,
|
n386con,
|
||||||
n386flw,
|
|
||||||
n386mem,
|
n386mem,
|
||||||
n386set,
|
n386set,
|
||||||
n386inl,
|
n386inl,
|
||||||
@ -61,7 +60,10 @@ unit cpunode;
|
|||||||
end.
|
end.
|
||||||
{
|
{
|
||||||
$Log$
|
$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
|
* tempgen cleanup
|
||||||
* tt_noreuse temp type added that will be used in genentrycode
|
* 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