mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-15 01:29:19 +02:00
* 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:
parent
96cab58ab4
commit
f6761d7939
@ -81,6 +81,7 @@ interface
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
tcgtryfinallynode = class(ttryfinallynode)
|
tcgtryfinallynode = class(ttryfinallynode)
|
||||||
|
procedure handle_safecall_exception;
|
||||||
procedure pass_generate_code;override;
|
procedure pass_generate_code;override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -1437,6 +1438,28 @@ implementation
|
|||||||
SecondTryFinally
|
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;
|
procedure tcgtryfinallynode.pass_generate_code;
|
||||||
var
|
var
|
||||||
reraiselabel,
|
reraiselabel,
|
||||||
@ -1451,7 +1474,6 @@ implementation
|
|||||||
oldflowcontrol,tryflowcontrol : tflowcontrol;
|
oldflowcontrol,tryflowcontrol : tflowcontrol;
|
||||||
decconst : longint;
|
decconst : longint;
|
||||||
excepttemps : texceptiontemps;
|
excepttemps : texceptiontemps;
|
||||||
retsym: tlocalvarsym;
|
|
||||||
begin
|
begin
|
||||||
location_reset(location,LOC_VOID,OS_NO);
|
location_reset(location,LOC_VOID,OS_NO);
|
||||||
|
|
||||||
@ -1541,15 +1563,7 @@ implementation
|
|||||||
{$if defined(x86) or defined(arm)}
|
{$if defined(x86) or defined(arm)}
|
||||||
if (tf_safecall_exceptions in target_info.flags) and
|
if (tf_safecall_exceptions in target_info.flags) and
|
||||||
(current_procinfo.procdef.proccalloption=pocall_safecall) then
|
(current_procinfo.procdef.proccalloption=pocall_safecall) then
|
||||||
begin
|
handle_safecall_exception
|
||||||
{ 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
|
|
||||||
else
|
else
|
||||||
{$endif}
|
{$endif}
|
||||||
cg.a_call_name(current_asmdata.CurrAsmList,'FPC_RERAISE',false);
|
cg.a_call_name(current_asmdata.CurrAsmList,'FPC_RERAISE',false);
|
||||||
|
@ -459,9 +459,6 @@ implementation
|
|||||||
function generate_except_block:tnode;
|
function generate_except_block:tnode;
|
||||||
var
|
var
|
||||||
newstatement : tstatementnode;
|
newstatement : tstatementnode;
|
||||||
{ safecall handling }
|
|
||||||
sym: tsym;
|
|
||||||
argnode: tnode;
|
|
||||||
begin
|
begin
|
||||||
generate_except_block:=internalstatements(newstatement);
|
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 paramanager.ret_in_param(current_procinfo.procdef.returndef, current_procinfo.procdef.proccalloption)) and
|
||||||
(not is_class(current_procinfo.procdef.returndef)) then
|
(not is_class(current_procinfo.procdef.returndef)) then
|
||||||
addstatement(newstatement,finalize_data_node(load_result_node));
|
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;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user