mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 14:21:27 +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