Преглед на файлове

* changed the abstract method wrapper generation from thlcgobj to synthetic
methods. Implementing a fully functional g_external_wrapper() for llvm is
quite hard, and the regular wrapper method that calls FPC_ABSTRACTERROR can
in principle be optimized to a plain jump by tail call optimisation on other
targets (to the extent that this matters, because most of them will be
smartlinked away, and the ones that are executed will trigger an exception)
o this means that the synthetic method generation needs to be run for all
objectdefs on all platforms now, rather than only for Java classes

git-svn-id: trunk@34127 -

Jonas Maebe преди 9 години
родител
ревизия
c0ff55e95a
променени са 7 файла, в които са добавени 46 реда и са изтрити 94 реда
  1. 0 1
      .gitattributes
  2. 1 1
      compiler/llvm/llvmnode.pas
  3. 0 69
      compiler/llvm/nllvmvmt.pas
  4. 15 18
      compiler/ncgvmt.pas
  5. 2 1
      compiler/symconst.pas
  6. 27 3
      compiler/symcreat.pas
  7. 1 1
      compiler/utils/ppuutils/ppudump.pp

+ 0 - 1
.gitattributes

@@ -352,7 +352,6 @@ compiler/llvm/nllvmmat.pas svneol=native#text/plain
 compiler/llvm/nllvmmem.pas svneol=native#text/plain
 compiler/llvm/nllvmmem.pas svneol=native#text/plain
 compiler/llvm/nllvmtcon.pas svneol=native#text/plain
 compiler/llvm/nllvmtcon.pas svneol=native#text/plain
 compiler/llvm/nllvmutil.pas svneol=native#text/plain
 compiler/llvm/nllvmutil.pas svneol=native#text/plain
-compiler/llvm/nllvmvmt.pas svneol=native#text/plain
 compiler/llvm/rgllvm.pas svneol=native#text/plain
 compiler/llvm/rgllvm.pas svneol=native#text/plain
 compiler/llvm/symllvm.pas svneol=native#text/plain
 compiler/llvm/symllvm.pas svneol=native#text/plain
 compiler/llvm/tgllvm.pas svneol=native#text/plain
 compiler/llvm/tgllvm.pas svneol=native#text/plain

+ 1 - 1
compiler/llvm/llvmnode.pas

@@ -38,7 +38,7 @@ implementation
     ncgadd,ncgcal,ncgmat,ncginl,
     ncgadd,ncgcal,ncgmat,ncginl,
     tgllvm,hlcgllvm,
     tgllvm,hlcgllvm,
     nllvmadd,nllvmbas,nllvmcal,nllvmcnv,nllvmcon,nllvminl,nllvmld,nllvmmat,
     nllvmadd,nllvmbas,nllvmcal,nllvmcnv,nllvmcon,nllvminl,nllvmld,nllvmmat,
-    nllvmmem,nllvmtcon,nllvmutil,nllvmvmt,
+    nllvmmem,nllvmtcon,nllvmutil,
     llvmpara,
     llvmpara,
     symllvm;
     symllvm;
 
 

+ 0 - 69
compiler/llvm/nllvmvmt.pas

@@ -1,69 +0,0 @@
-{
-    Copyright (c) 2015 by Jonas Maebe
-
-    Generate LLVM IR for VMT generation
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
- ****************************************************************************
-}
-unit nllvmvmt;
-
-{$i fpcdefs.inc}
-
-interface
-
-    uses
-      aasmdata,
-      ncgvmt,
-      symdef;
-
-    type
-      tllvmvmtwriter = class(TVMTWriter)
-      protected
-        procedure generate_abstract_stub(list:TAsmList;pd:tprocdef); override;
-      end;
-
-
-implementation
-
-  uses
-    globtype,globals,
-    aasmbase,
-    symconst,
-    hlcgobj;
-
-
-{*****************************************************************************
-                             TLLVMVMTWRITER
-*****************************************************************************}
-
-
-  procedure tllvmvmtwriter.generate_abstract_stub(list: TAsmList; pd: tprocdef);
-    var
-      sym: TAsmSymbol;
-    begin
-      if (po_global in pd.procoptions) and
-         (pd.owner.defowner<>self._class) then
-        exit;
-      sym:=current_asmdata.GetAsmSymbol(pd.mangledname);
-      if assigned(sym) and (sym.bind<>AB_EXTERNAL) then
-        exit;
-      hlcg.g_external_wrapper(list,pd,'FPC_ABSTRACTERROR');
-    end;
-
-begin
-  CVMTWriter:=tllvmvmtwriter;
-end.

+ 15 - 18
compiler/ncgvmt.pas

@@ -117,7 +117,10 @@ implementation
       aasmtai,
       aasmtai,
       wpobase,
       wpobase,
       nobj,
       nobj,
-      cgbase,parabase,paramgr,cgobj,cgcpu,hlcgobj,hlcgcpu,
+      cgbase,parabase,paramgr,
+{$ifndef cpuhighleveltarget}
+      cgobj,cgcpu,hlcgobj,hlcgcpu,
+{$endif not cpuhighleveltarget}
       ncgrtti;
       ncgrtti;
 
 
 
 
@@ -971,23 +974,13 @@ implementation
         if (po_global in pd.procoptions) and
         if (po_global in pd.procoptions) and
            (pd.owner.defowner<>self._class) then
            (pd.owner.defowner<>self._class) then
           exit;
           exit;
-        sym:=current_asmdata.GetAsmSymbol(pd.mangledname);
-        if assigned(sym) and (sym.bind<>AB_EXTERNAL) then
-          exit;
-        maybe_new_object_file(list);
-        new_section(list,sec_code,lower(pd.mangledname),target_info.alignment.procalign);
-        if (po_global in pd.procoptions) then
-          begin
-            sym:=current_asmdata.DefineAsmSymbol(pd.mangledname,AB_GLOBAL,AT_FUNCTION);
-            list.concat(Tai_symbol.Create_global(sym,0));
-          end
-        else
-          begin
-            sym:=current_asmdata.DefineAsmSymbol(pd.mangledname,AB_LOCAL,AT_FUNCTION);
-            list.concat(Tai_symbol.Create(sym,0));
-          end;
-        hlcg.g_external_wrapper(list,pd,'FPC_ABSTRACTERROR');
-        list.concat(Tai_symbol_end.Create(sym));
+        pd.synthetickind:=tsk_call_no_parameters;
+        pd.skpara:=search_system_proc('ABSTRACTERROR');
+        { abstract methods are not marked as forwarddef, because otherwise
+          the compiler would accept implementations for them (and complain if
+          they were missing); we are now after parsing the user code, so we can
+          mark them again as forwarddef to indicate they need to be parsed }
+        pd.forwarddef:=true;
       end;
       end;
 
 
 
 
@@ -1348,9 +1341,13 @@ implementation
 
 
     procedure write_vmts(st:tsymtable;is_global:boolean);
     procedure write_vmts(st:tsymtable;is_global:boolean);
       begin
       begin
+{$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.

+ 2 - 1
compiler/symconst.pas

@@ -432,7 +432,8 @@ type
     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
+    tsk_interface_wrapper,     // Call through to a method from an interface wrapper
+    tsk_call_no_parameters     // Call skpara procedure without passing any parameters nor returning a result
   );
   );
 
 
   { synthetic procdef supplementary information (tprocdef.skpara) }
   { synthetic procdef supplementary information (tprocdef.skpara) }

+ 27 - 3
compiler/symcreat.pas

@@ -977,6 +977,28 @@ implementation
       pd.skpara:=nil;
       pd.skpara:=nil;
     end;
     end;
 
 
+
+  procedure implement_call_no_parameters(pd: tprocdef);
+    var
+      callpd: tprocdef;
+      str: ansistring;
+      isclassmethod: boolean;
+    begin
+      str:='begin ';
+      callpd:=tprocdef(pd.skpara);
+      str:=str+def_unit_name_prefix_if_toplevel(callpd)+callpd.procsym.realname+'; ';
+      { avoid warnings about unset function results }
+      if (pd.proctypeoption<>potype_constructor) and
+         not is_void(pd.returndef) then
+        str:=str+'result:=system.default('+def_unit_name_prefix_if_toplevel(pd.returndef)+pd.returndef.typename+'); ';
+      str:=str+'end;';
+      isclassmethod:=
+        (po_classmethod in pd.procoptions) and
+        not(pd.proctypeoption in [potype_constructor,potype_destructor]);
+      str_parse_method_impl(str,pd,isclassmethod);
+    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;
@@ -1051,6 +1073,8 @@ implementation
               implement_block_invoke_procvar(pd);
               implement_block_invoke_procvar(pd);
             tsk_interface_wrapper:
             tsk_interface_wrapper:
               implement_interface_wrapper(pd);
               implement_interface_wrapper(pd);
+            tsk_call_no_parameters:
+              implement_call_no_parameters(pd);
             else
             else
               internalerror(2011032801);
               internalerror(2011032801);
           end;
           end;
@@ -1078,9 +1102,9 @@ implementation
              { not true for the "main" procedure, whose localsymtable is the staticsymtable }
              { not true for the "main" procedure, whose localsymtable is the staticsymtable }
              (tprocdef(def).localst.symtabletype=localsymtable) then
              (tprocdef(def).localst.symtabletype=localsymtable) then
             add_synthetic_method_implementations(tprocdef(def).localst)
             add_synthetic_method_implementations(tprocdef(def).localst)
-          else if (is_javaclass(def) and
-              not(oo_is_external in tobjectdef(def).objectoptions)) or
-              (def.typ=recorddef) then
+          else if ((def.typ=objectdef) and
+                   not(oo_is_external in tobjectdef(def).objectoptions)) or
+                  (def.typ=recorddef) then
            begin
            begin
             { also complete nested types }
             { also complete nested types }
             add_synthetic_method_implementations(tabstractrecorddef(def).symtable);
             add_synthetic_method_implementations(tabstractrecorddef(def).symtable);

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

@@ -542,7 +542,7 @@ const
       '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',
       'jvm virtual class method', 'jvm field getter', 'jvm field setter',
-      'block invoke','interface wrapper');
+      'block invoke','interface wrapper','call parameterless routine');
 begin
 begin
   if w<=ord(high(syntheticName)) then
   if w<=ord(high(syntheticName)) then
     result:=syntheticName[tsynthetickind(w)]
     result:=syntheticName[tsynthetickind(w)]