mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-14 06:49:23 +02:00
compiler,rtl - safecall handling:
- pass address to SafeCallException method(rtl needed a modification) - improve code generation for regular safecall routines (not methods) - improve test - check that passed exception and address are valid git-svn-id: trunk@14946 -
This commit is contained in:
parent
a0ad752e16
commit
fcaac0ebe1
@ -476,7 +476,7 @@ implementation
|
|||||||
newstatement : tstatementnode;
|
newstatement : tstatementnode;
|
||||||
oldlocalswitches: tlocalswitches;
|
oldlocalswitches: tlocalswitches;
|
||||||
{ safecall handling }
|
{ safecall handling }
|
||||||
exceptnode: ttempcreatenode;
|
exceptobjnode,exceptaddrnode: ttempcreatenode;
|
||||||
sym,exceptsym: tsym;
|
sym,exceptsym: tsym;
|
||||||
begin
|
begin
|
||||||
generate_except_block:=internalstatements(newstatement);
|
generate_except_block:=internalstatements(newstatement);
|
||||||
@ -524,37 +524,50 @@ implementation
|
|||||||
sym:=tlocalvarsym.create('$safe_result',vs_value,hresultdef,[]);
|
sym:=tlocalvarsym.create('$safe_result',vs_value,hresultdef,[]);
|
||||||
include(sym.symoptions,sp_internal);
|
include(sym.symoptions,sp_internal);
|
||||||
current_procinfo.procdef.localst.insert(sym);
|
current_procinfo.procdef.localst.insert(sym);
|
||||||
{ temp variable to store popped up exception }
|
|
||||||
exceptnode:=ctempcreatenode.create(class_tobject,class_tobject.size,
|
|
||||||
tt_persistent,true);
|
|
||||||
addstatement(newstatement,exceptnode);
|
|
||||||
addstatement(newstatement,
|
|
||||||
cassignmentnode.create(
|
|
||||||
ctemprefnode.create(exceptnode),
|
|
||||||
ccallnode.createintern('fpc_popobjectstack', nil)));
|
|
||||||
{ if safecall is used for a class method we need to call }
|
{ if safecall is used for a class method we need to call }
|
||||||
{ SafecallException virtual method }
|
{ SafecallException virtual method }
|
||||||
{ In other case we return E_UNEXPECTED error value }
|
{ In other case we return E_UNEXPECTED error value }
|
||||||
if is_class(current_procinfo.procdef._class) then
|
if is_class(current_procinfo.procdef._class) then
|
||||||
begin
|
begin
|
||||||
|
{ temp variable to store exception address }
|
||||||
|
exceptaddrnode:=ctempcreatenode.create(voidpointertype,voidpointertype.size,
|
||||||
|
tt_persistent,true);
|
||||||
|
addstatement(newstatement,exceptaddrnode);
|
||||||
|
addstatement(newstatement,
|
||||||
|
cassignmentnode.create(
|
||||||
|
ctemprefnode.create(exceptaddrnode),
|
||||||
|
ccallnode.createintern('fpc_getexceptionaddr',nil)));
|
||||||
|
{ temp variable to store popped up exception }
|
||||||
|
exceptobjnode:=ctempcreatenode.create(class_tobject,class_tobject.size,
|
||||||
|
tt_persistent,true);
|
||||||
|
addstatement(newstatement,exceptobjnode);
|
||||||
|
addstatement(newstatement,
|
||||||
|
cassignmentnode.create(
|
||||||
|
ctemprefnode.create(exceptobjnode),
|
||||||
|
ccallnode.createintern('fpc_popobjectstack', nil)));
|
||||||
exceptsym:=search_class_member(current_procinfo.procdef._class,'SAFECALLEXCEPTION');
|
exceptsym:=search_class_member(current_procinfo.procdef._class,'SAFECALLEXCEPTION');
|
||||||
addstatement(newstatement,
|
addstatement(newstatement,
|
||||||
cassignmentnode.create(
|
cassignmentnode.create(
|
||||||
cloadnode.create(sym,sym.Owner),
|
cloadnode.create(sym,sym.Owner),
|
||||||
ccallnode.create(
|
ccallnode.create(
|
||||||
ccallparanode.create(cpointerconstnode.create(0,voidpointertype),
|
ccallparanode.create(ctemprefnode.create(exceptaddrnode),
|
||||||
ccallparanode.create(ctemprefnode.create(exceptnode),nil)),
|
ccallparanode.create(ctemprefnode.create(exceptobjnode),nil)),
|
||||||
tprocsym(exceptsym), tprocsym(exceptsym).owner,load_self_node,[])));
|
tprocsym(exceptsym), tprocsym(exceptsym).owner,load_self_node,[])));
|
||||||
|
addstatement(newstatement,ccallnode.createintern('fpc_destroyexception',
|
||||||
|
ccallparanode.create(ctemprefnode.create(exceptobjnode),nil)));
|
||||||
|
addstatement(newstatement,ctempdeletenode.create(exceptobjnode));
|
||||||
|
addstatement(newstatement,ctempdeletenode.create(exceptaddrnode));
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
addstatement(newstatement,
|
begin
|
||||||
cassignmentnode.create(
|
{ pop up and destroy an exception }
|
||||||
cloadnode.create(sym,sym.Owner),
|
addstatement(newstatement,ccallnode.createintern('fpc_destroyexception',
|
||||||
genintconstnode(HResult($8000FFFF))));
|
ccallparanode.create(ccallnode.createintern('fpc_popobjectstack', nil),nil)));
|
||||||
{ destroy popped up exception }
|
addstatement(newstatement,
|
||||||
addstatement(newstatement,ccallnode.createintern('fpc_destroyexception',
|
cassignmentnode.create(
|
||||||
ccallparanode.create(ctemprefnode.create(exceptnode),nil)));
|
cloadnode.create(sym,sym.Owner),
|
||||||
addstatement(newstatement,ctempdeletenode.create(exceptnode));
|
genintconstnode(HResult($8000FFFF))));
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
{$endif}
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
@ -609,6 +609,7 @@ function fpc_PopSecondObjectStack : TObject; compilerproc;
|
|||||||
Procedure fpc_ReRaise; compilerproc;
|
Procedure fpc_ReRaise; compilerproc;
|
||||||
Function fpc_Catches(Objtype : TClass) : TObject; compilerproc;
|
Function fpc_Catches(Objtype : TClass) : TObject; compilerproc;
|
||||||
Procedure fpc_DestroyException(o : TObject); compilerproc;
|
Procedure fpc_DestroyException(o : TObject); compilerproc;
|
||||||
|
function fpc_GetExceptionAddr : Pointer; compilerproc;
|
||||||
{$endif FPC_HAS_FEATURE_EXCEPTIONS}
|
{$endif FPC_HAS_FEATURE_EXCEPTIONS}
|
||||||
|
|
||||||
|
|
||||||
|
@ -343,6 +343,16 @@ begin
|
|||||||
o.Free;
|
o.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function fpc_GetExceptionAddr : Pointer;[Public, Alias : 'FPC_GETEXCEPTIONADDR']; compilerproc;
|
||||||
|
var
|
||||||
|
_ExceptObjectStack : PExceptObject;
|
||||||
|
begin
|
||||||
|
_ExceptObjectStack:=ExceptObjectStack;
|
||||||
|
if _ExceptObjectStack=nil then
|
||||||
|
fpc_GetExceptionAddr:=nil
|
||||||
|
else
|
||||||
|
fpc_GetExceptionAddr:=_ExceptObjectStack^.Addr;
|
||||||
|
end;
|
||||||
|
|
||||||
Procedure SysInitExceptions;
|
Procedure SysInitExceptions;
|
||||||
{
|
{
|
||||||
|
@ -12,15 +12,21 @@ type
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
|
ExceptObj: TObject;
|
||||||
Handled: Boolean;
|
Handled: Boolean;
|
||||||
|
|
||||||
procedure TTest.SomeError; safecall;
|
procedure TTest.SomeError; safecall;
|
||||||
begin
|
begin
|
||||||
raise Exception.Create('SomeException');
|
ExceptObj := Exception.Create('SomeException');
|
||||||
|
raise ExceptObj;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TTest.SafeCallException(ExceptObject: TObject; ExceptAddr: Pointer): HResult;
|
function TTest.SafeCallException(ExceptObject: TObject; ExceptAddr: Pointer): HResult;
|
||||||
begin
|
begin
|
||||||
|
if ExceptAddr = nil then
|
||||||
|
halt(2);
|
||||||
|
if ExceptObject <> ExceptObj then
|
||||||
|
halt(3);
|
||||||
Handled := True;
|
Handled := True;
|
||||||
Result := 0;
|
Result := 0;
|
||||||
end;
|
end;
|
||||||
@ -30,4 +36,4 @@ begin
|
|||||||
TTest.Create.SomeError;
|
TTest.Create.SomeError;
|
||||||
if not Handled then
|
if not Handled then
|
||||||
halt(1);
|
halt(1);
|
||||||
end.
|
end.
|
||||||
|
Loading…
Reference in New Issue
Block a user