mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 11:53:42 +01: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
	 paul
						paul