mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-10-31 16:31:36 +01:00 
			
		
		
		
	* support for implementing interface method wrappers at the node tree
level, used by LLVM git-svn-id: trunk@31636 -
This commit is contained in:
		
							parent
							
								
									be2ec5be59
								
							
						
					
					
						commit
						c7a418829b
					
				| @ -110,15 +110,14 @@ implementation | |||||||
|       cutils,cclasses, |       cutils,cclasses, | ||||||
|       globtype,globals,verbose,constexp, |       globtype,globals,verbose,constexp, | ||||||
|       systems,fmodule, |       systems,fmodule, | ||||||
|       symsym,symtable,defutil, |       symsym,symtable,symcreat,defutil, | ||||||
|  | {$ifdef cpuhighleveltarget} | ||||||
|  |       pparautl, | ||||||
|  | {$endif cpuhighleveltarget} | ||||||
|       aasmtai, |       aasmtai, | ||||||
|       wpobase, |       wpobase, | ||||||
|       nobj, |       nobj, | ||||||
|       cgbase,parabase,paramgr,cgobj,cgcpu,hlcgobj,hlcgcpu, |       cgbase,parabase,paramgr,cgobj,cgcpu,hlcgobj,hlcgcpu, | ||||||
| {$ifdef llvm} |  | ||||||
|       { override create_hlcodegen from hlcgcpu } |  | ||||||
|       hlcgllvm, |  | ||||||
| {$endif} |  | ||||||
|       ncgrtti; |       ncgrtti; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -1239,6 +1238,10 @@ implementation | |||||||
|         tmps : string; |         tmps : string; | ||||||
|         pd   : TProcdef; |         pd   : TProcdef; | ||||||
|         ImplIntf : TImplementedInterface; |         ImplIntf : TImplementedInterface; | ||||||
|  | {$ifdef cpuhighleveltarget} | ||||||
|  |         wrapperpd: tprocdef; | ||||||
|  |         wrapperinfo: pskpara_interface_wrapper; | ||||||
|  | {$endif cpuhighleveltarget} | ||||||
|       begin |       begin | ||||||
|         for i:=0 to _class.ImplementedInterfaces.count-1 do |         for i:=0 to _class.ImplementedInterfaces.count-1 do | ||||||
|           begin |           begin | ||||||
| @ -1257,11 +1260,34 @@ implementation | |||||||
|                       tobjectdef(tprocdef(pd).struct).register_vmt_call(tprocdef(pd).extnumber); |                       tobjectdef(tprocdef(pd).struct).register_vmt_call(tprocdef(pd).extnumber); | ||||||
|                     tmps:=make_mangledname('WRPR',_class.owner,_class.objname^+'_$_'+ |                     tmps:=make_mangledname('WRPR',_class.owner,_class.objname^+'_$_'+ | ||||||
|                       ImplIntf.IntfDef.objname^+'_$_'+tostr(j)+'_$_'+pd.mangledname); |                       ImplIntf.IntfDef.objname^+'_$_'+tostr(j)+'_$_'+pd.mangledname); | ||||||
|  | {$ifdef cpuhighleveltarget} | ||||||
|  |                     { bare copy so we don't copy the aliasnames } | ||||||
|  |                     wrapperpd:=tprocdef(pd.getcopyas(procdef,pc_bareproc)); | ||||||
|  |                     { set the mangled name to the wrapper name } | ||||||
|  |                     wrapperpd.setmangledname(tmps); | ||||||
|  |                     { insert the wrapper procdef in the current unit's local | ||||||
|  |                       symbol table, but set the owning "struct" to the current | ||||||
|  |                       class (so self will have the correct type) } | ||||||
|  |                     finish_copied_procdef(wrapperpd,tmps,current_module.localsymtable,_class); | ||||||
|  |                     { now insert self/vmt } | ||||||
|  |                     insert_self_and_vmt_para(wrapperpd); | ||||||
|  |                     { and the function result } | ||||||
|  |                     insert_funcret_para(wrapperpd); | ||||||
|  |                     { recalculate the parameters now that we've added the above } | ||||||
|  |                     wrapperpd.calcparas; | ||||||
|  |                     { set the info required to generate the implementation } | ||||||
|  |                     wrapperpd.synthetickind:=tsk_interface_wrapper; | ||||||
|  |                     new(wrapperinfo); | ||||||
|  |                     wrapperinfo^.pd:=pd; | ||||||
|  |                     wrapperinfo^.offset:=ImplIntf.ioffset; | ||||||
|  |                     wrapperpd.skpara:=wrapperinfo; | ||||||
|  | {$else cpuhighleveltarget} | ||||||
|                     { create wrapper code } |                     { create wrapper code } | ||||||
|                     new_section(list,sec_code,tmps,target_info.alignment.procalign); |                     new_section(list,sec_code,tmps,target_info.alignment.procalign); | ||||||
|                     hlcg.init_register_allocators; |                     hlcg.init_register_allocators; | ||||||
|                     hlcg.g_intf_wrapper(list,pd,tmps,ImplIntf.ioffset); |                     hlcg.g_intf_wrapper(list,pd,tmps,ImplIntf.ioffset); | ||||||
|                     hlcg.done_register_allocators; |                     hlcg.done_register_allocators; | ||||||
|  | {$endif cpuhighleveltarget} | ||||||
|                   end; |                   end; | ||||||
|               end; |               end; | ||||||
|           end; |           end; | ||||||
| @ -1317,9 +1343,15 @@ implementation | |||||||
| 
 | 
 | ||||||
|     procedure write_vmts(st:tsymtable;is_global:boolean); |     procedure write_vmts(st:tsymtable;is_global:boolean); | ||||||
|       begin |       begin | ||||||
|  |         { high level targets use synthetic procdefs to create the inteface | ||||||
|  |           wrappers } | ||||||
|  | {$ifndef cpuhighleveltarget} | ||||||
|         create_hlcodegen; |         create_hlcodegen; | ||||||
|  | {$endif} | ||||||
|         do_write_vmts(st,is_global); |         do_write_vmts(st,is_global); | ||||||
|  | {$ifndef cpuhighleveltarget} | ||||||
|         destroy_hlcodegen; |         destroy_hlcodegen; | ||||||
|  | {$endif} | ||||||
|       end; |       end; | ||||||
| 
 | 
 | ||||||
| end. | end. | ||||||
|  | |||||||
| @ -401,9 +401,17 @@ type | |||||||
|     tsk_jvm_virtual_clmethod,  // Java wrapper for virtual class method |     tsk_jvm_virtual_clmethod,  // Java wrapper for virtual class method | ||||||
|     tsk_field_getter,          // getter for a field (callthrough property is passed in skpara) |     tsk_field_getter,          // getter for a field (callthrough property is passed in skpara) | ||||||
|     tsk_field_setter,          // Setter for a field (callthrough property is passed in skpara) |     tsk_field_setter,          // Setter for a field (callthrough property is passed in skpara) | ||||||
|     tsk_block_invoke_procvar   // Call a procvar to invoke inside a block |     tsk_block_invoke_procvar,  // Call a procvar to invoke inside a block | ||||||
|  |     tsk_interface_wrapper      // Call through to a method from an interface wrapper | ||||||
|   ); |   ); | ||||||
| 
 | 
 | ||||||
|  |   { synthetic procdef supplementary information (tprocdef.skpara) } | ||||||
|  |   tskpara_interface_wrapper = record | ||||||
|  |     pd: pointer; | ||||||
|  |     offset: longint; | ||||||
|  |   end; | ||||||
|  |   pskpara_interface_wrapper = ^tskpara_interface_wrapper; | ||||||
|  | 
 | ||||||
|   { options for objects and classes } |   { options for objects and classes } | ||||||
|   tobjecttyp = (odt_none, |   tobjecttyp = (odt_none, | ||||||
|     odt_class, |     odt_class, | ||||||
|  | |||||||
| @ -935,6 +935,32 @@ implementation | |||||||
|       str_parse_method_impl(str,pd,false); |       str_parse_method_impl(str,pd,false); | ||||||
|     end; |     end; | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |   procedure implement_interface_wrapper(pd: tprocdef); | ||||||
|  |     var | ||||||
|  |       wrapperinfo: pskpara_interface_wrapper; | ||||||
|  |       callthroughpd: tprocdef; | ||||||
|  |       str: ansistring; | ||||||
|  |     begin | ||||||
|  |       wrapperinfo:=pskpara_interface_wrapper(pd.skpara); | ||||||
|  |       if not assigned(wrapperinfo) then | ||||||
|  |         internalerror(2015090801); | ||||||
|  |       callthroughpd:=tprocdef(wrapperinfo^.pd); | ||||||
|  |       str:='begin '; | ||||||
|  |       { self right now points to the VMT of interface inside the instance -> | ||||||
|  |         adjust so it points to the start of the instance } | ||||||
|  |       str:=str+'pointer(self):=pointer(self) - '+tostr(wrapperinfo^.offset)+';'; | ||||||
|  |       { now call through to the actual method } | ||||||
|  |       if pd.returndef<>voidtype then | ||||||
|  |         str:=str+'result:='; | ||||||
|  |       str:=str+callthroughpd.procsym.realname+'('; | ||||||
|  |       addvisibibleparameters(str,callthroughpd); | ||||||
|  |       str:=str+') end;'; | ||||||
|  |       str_parse_method_impl(str,pd,false); | ||||||
|  |       dispose(wrapperinfo); | ||||||
|  |       pd.skpara:=nil; | ||||||
|  |     end; | ||||||
|  | 
 | ||||||
|   procedure add_synthetic_method_implementations_for_st(st: tsymtable); |   procedure add_synthetic_method_implementations_for_st(st: tsymtable); | ||||||
|     var |     var | ||||||
|       i   : longint; |       i   : longint; | ||||||
| @ -1007,6 +1033,8 @@ implementation | |||||||
|               implement_field_setter(pd); |               implement_field_setter(pd); | ||||||
|             tsk_block_invoke_procvar: |             tsk_block_invoke_procvar: | ||||||
|               implement_block_invoke_procvar(pd); |               implement_block_invoke_procvar(pd); | ||||||
|  |             tsk_interface_wrapper: | ||||||
|  |               implement_interface_wrapper(pd); | ||||||
|             else |             else | ||||||
|               internalerror(2011032801); |               internalerror(2011032801); | ||||||
|           end; |           end; | ||||||
|  | |||||||
| @ -539,7 +539,8 @@ const | |||||||
|       'jvm enum fpcvalueof', 'jvm enum long2set', |       'jvm enum fpcvalueof', 'jvm enum long2set', | ||||||
|       'jvm enum bitset2set', 'jvm enum set2set', |       'jvm enum bitset2set', 'jvm enum set2set', | ||||||
|       'jvm procvar invoke', 'jvm procvar intf constructor', |       'jvm procvar invoke', 'jvm procvar intf constructor', | ||||||
|       'jvm virtual class method', 'jvm field getter', 'jvm field setter', 'block invoke'); |       'jvm virtual class method', 'jvm field getter', 'jvm field setter', | ||||||
|  |       'block invoke','interface wrapper'); | ||||||
| begin | begin | ||||||
|   if w<=ord(high(syntheticName)) then |   if w<=ord(high(syntheticName)) then | ||||||
|     result:=syntheticName[tsynthetickind(w)] |     result:=syntheticName[tsynthetickind(w)] | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Jonas Maebe
						Jonas Maebe