|
@@ -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
|
|
|
-
|
|
|
-}
|