* Handle safecall exceptions entirely in tcgtryfinallynode pass2. This simplifies things and removes the need in hidden safe_result variable.

git-svn-id: trunk@19950 -
This commit is contained in:
sergei 2012-01-02 14:23:31 +00:00
parent 96cab58ab4
commit f6761d7939
2 changed files with 24 additions and 37 deletions

View File

@ -81,6 +81,7 @@ interface
end;
tcgtryfinallynode = class(ttryfinallynode)
procedure handle_safecall_exception;
procedure pass_generate_code;override;
end;
@ -1437,6 +1438,28 @@ implementation
SecondTryFinally
*****************************************************************************}
procedure tcgtryfinallynode.handle_safecall_exception;
var
cgpara: tcgpara;
selfsym: tparavarsym;
begin
{ call fpc_safecallhandler, passing self for methods of classes,
nil otherwise. }
cgpara.init;
paramanager.getintparaloc(pocall_default,1,cgpara);
if is_class(current_procinfo.procdef.struct) then
begin
selfsym:=tparavarsym(current_procinfo.procdef.parast.Find('self'));
if (selfsym=nil) or (selfsym.typ<>paravarsym) then
InternalError(2011123101);
cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,selfsym.localloc,cgpara);
end
else
cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_ADDR,0,cgpara);
cgpara.done;
cg.g_call(current_asmdata.CurrAsmList,'FPC_SAFECALLHANDLER');
end;
procedure tcgtryfinallynode.pass_generate_code;
var
reraiselabel,
@ -1451,7 +1474,6 @@ implementation
oldflowcontrol,tryflowcontrol : tflowcontrol;
decconst : longint;
excepttemps : texceptiontemps;
retsym: tlocalvarsym;
begin
location_reset(location,LOC_VOID,OS_NO);
@ -1541,15 +1563,7 @@ implementation
{$if defined(x86) or defined(arm)}
if (tf_safecall_exceptions in target_info.flags) and
(current_procinfo.procdef.proccalloption=pocall_safecall) then
begin
{ find safe_result variable we created in the generate_except_block }
retsym:=tlocalvarsym(current_procinfo.procdef.localst.Find('safe_result'));
{ Set return value of safecall procedure to indicate exception. }
{ Exception will be raised after procedure exit based on return value }
cg.a_reg_alloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
cg.a_load_loc_reg(current_asmdata.CurrAsmList,OS_INT,retsym.localloc,NR_FUNCTION_RESULT_REG);
cg.a_reg_dealloc(current_asmdata.CurrAsmList,NR_FUNCTION_RESULT_REG);
end
handle_safecall_exception
else
{$endif}
cg.a_call_name(current_asmdata.CurrAsmList,'FPC_RERAISE',false);

View File

@ -459,9 +459,6 @@ implementation
function generate_except_block:tnode;
var
newstatement : tstatementnode;
{ safecall handling }
sym: tsym;
argnode: tnode;
begin
generate_except_block:=internalstatements(newstatement);
@ -477,30 +474,6 @@ implementation
(not paramanager.ret_in_param(current_procinfo.procdef.returndef, current_procinfo.procdef.proccalloption)) and
(not is_class(current_procinfo.procdef.returndef)) then
addstatement(newstatement,finalize_data_node(load_result_node));
{$if defined(x86) or defined(arm)}
{ safecall handling }
if (tf_safecall_exceptions in target_info.flags) and
(current_procinfo.procdef.proccalloption=pocall_safecall) then
begin
{ create a local hidden variable "safe_result" }
{ it will be used in ncgflw unit }
{ to set "real" result value for safecall routine }
sym:=tlocalvarsym.create('$safe_result',vs_value,hresultdef,[]);
include(sym.symoptions,sp_internal);
current_procinfo.procdef.localst.insert(sym);
{ if safecall is used for a class method we need to call }
{ SafecallException virtual method }
{ In other case we return E_UNEXPECTED error value }
if is_class(current_procinfo.procdef.struct) then
argnode:=load_self_node
else
argnode:=cnilnode.create;
addstatement(newstatement,cassignmentnode.create(
cloadnode.create(sym,sym.Owner),
ccallnode.createinternres('fpc_safecallhandler',
ccallparanode.create(argnode,nil),hresultdef)));
end;
{$endif}
end;
end;