소스 검색

* support for implementing interface method wrappers at the node tree
level, used by LLVM

git-svn-id: trunk@31636 -

Jonas Maebe 10 년 전
부모
커밋
c7a418829b
4개의 변경된 파일76개의 추가작업 그리고 7개의 파일을 삭제
  1. 37 5
      compiler/ncgvmt.pas
  2. 9 1
      compiler/symconst.pas
  3. 28 0
      compiler/symcreat.pas
  4. 2 1
      compiler/utils/ppuutils/ppudump.pp

+ 37 - 5
compiler/ncgvmt.pas

@@ -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.

+ 9 - 1
compiler/symconst.pas

@@ -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,

+ 28 - 0
compiler/symcreat.pas

@@ -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;

+ 2 - 1
compiler/utils/ppuutils/ppudump.pp

@@ -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)]