Browse Source

* extract calculation of unit init/fini entries into separate method get_init_final_list() so that it can be used by the AVR code as well

git-svn-id: trunk@36257 -
svenbarth 8 năm trước cách đây
mục cha
commit
d311881b34
1 tập tin đã thay đổi với 183 bổ sung100 xóa
  1. 183 100
      compiler/ngenutil.pas

+ 183 - 100
compiler/ngenutil.pas

@@ -28,11 +28,21 @@ interface
 
   uses
     cclasses,globtype,
+    fmodule,
     aasmdata,
     node,nbas,symtype,symsym,symconst,symdef;
 
 
   type
+    tinitfinalentry = record
+      initfunc : TSymStr;
+      finifunc : TSymStr;
+      initpd : tprocdef;
+      finipd : tprocdef;
+      module : tmodule;
+    end;
+    pinitfinalentry = ^tinitfinalentry;
+
     tnodeutils = class
       class function call_fail_node:tnode; virtual;
       class function initialize_data_node(p:tnode; force: boolean):tnode; virtual;
@@ -103,6 +113,9 @@ interface
      protected
       class procedure InsertRuntimeInits(const prefix:string;list:TLinkedList;unitflag:cardinal); virtual;
       class procedure InsertRuntimeInitsTablesTable(const prefix,tablename:string;unitflag:cardinal); virtual;
+
+      class function get_init_final_list: tfplist;
+      class procedure release_init_final_list(list:tfplist);
      public
       class procedure InsertThreadvarTablesTable; virtual;
       class procedure InsertThreadvars; virtual;
@@ -133,7 +146,7 @@ implementation
 
     uses
       verbose,version,globals,cutils,constexp,compinnr,
-      systems,procinfo,fmodule,pparautl,
+      systems,procinfo,pparautl,
       aasmbase,aasmtai,aasmcnst,
       symbase,symtable,defutil,
       nadd,ncal,ncnv,ncon,nflw,ninl,nld,nmem,nutils,
@@ -890,50 +903,127 @@ implementation
     end;
 
 
-  class procedure tnodeutils.InsertInitFinalTable;
+  class function tnodeutils.get_init_final_list:tfplist;
+
+    procedure append_struct_inits(u:tmodule);
+      var
+        i : integer;
+        structlist : tfplist;
+        pd : tprocdef;
+        entry : pinitfinalentry;
+      begin
+        structlist:=tfplist.Create;
+        if assigned(u.globalsymtable) then
+          u.globalsymtable.DefList.ForEachCall(@AddToStructInits,structlist);
+        u.localsymtable.DefList.ForEachCall(@AddToStructInits,structlist);
+        { write structures }
+        for i:=0 to structlist.Count-1 do
+        begin
+          new(entry);
+          entry^.module:=u;
+          pd:=tabstractrecorddef(structlist[i]).find_procdef_bytype(potype_class_constructor);
+          if assigned(pd) then
+            begin
+              entry^.initfunc:=pd.mangledname;
+              entry^.initpd:=pd;
+            end
+          else
+            begin
+              entry^.initfunc:='';
+              entry^.initpd:=nil;
+            end;
+          pd := tabstractrecorddef(structlist[i]).find_procdef_bytype(potype_class_destructor);
+          if assigned(pd) then
+            begin
+              entry^.finifunc:=pd.mangledname;
+              entry^.finipd:=pd;
+            end
+          else
+            begin
+              entry^.finifunc:='';
+              entry^.finipd:=nil;
+            end;
+          if assigned(entry^.finipd) or assigned(entry^.initpd) then
+            result.add(entry)
+          else
+            { AddToStructInits only adds structs that have either a class constructor or destructor or both }
+            internalerror(2017051902);
+        end;
+        structlist.free;
+      end;
+
     var
       hp : tused_unit;
-      unitinits : ttai_typedconstbuilder;
-      count : aint;
-      tablecountplaceholder: ttypedconstplaceholder;
-      nameinit,namefini : TSymStr;
-      tabledef: tdef;
+      entry : pinitfinalentry;
+    begin
+      result:=tfplist.create;
+      hp:=tused_unit(usedunits.first);
+      while assigned(hp) do
+       begin
+         { insert class constructors/destructors of the unit }
+         if (hp.u.flags and uf_classinits) <> 0 then
+           append_struct_inits(hp.u);
+         if (hp.u.flags and (uf_init or uf_finalize))<>0 then
+           begin
+             new(entry);
+             entry^.module:=hp.u;
+             entry^.initpd:=nil;
+             entry^.finipd:=nil;
+             if (hp.u.flags and uf_init)<>0 then
+               entry^.initfunc:=make_mangledname('INIT$',hp.u.globalsymtable,'')
+             else
+               entry^.initfunc:='';
+             if (hp.u.flags and uf_finalize)<>0 then
+               entry^.finifunc:=make_mangledname('FINALIZE$',hp.u.globalsymtable,'')
+             else
+               entry^.finifunc:='';
+             result.add(entry);
+           end;
+         hp:=tused_unit(hp.next);
+       end;
 
-      procedure write_struct_inits(u: tmodule);
-        var
-          i: integer;
-          structlist: TFPList;
-          pd: tprocdef;
+      if (current_module.flags and uf_classinits) <> 0 then
+        append_struct_inits(current_module);
+      { Insert initialization/finalization of the program }
+      if (current_module.flags and (uf_init or uf_finalize))<>0 then
         begin
-          structlist := TFPList.Create;
-          if assigned(u.globalsymtable) then
-            u.globalsymtable.DefList.ForEachCall(@AddToStructInits,structlist);
-          u.localsymtable.DefList.ForEachCall(@AddToStructInits,structlist);
-          { write structures }
-          for i:=0 to structlist.Count-1 do
-          begin
-            pd:=tabstractrecorddef(structlist[i]).find_procdef_bytype(potype_class_constructor);
-            if assigned(pd) then
-              begin
-                unitinits.emit_procdef_const(pd);
-                if u<>current_module then
-                  current_module.addimportedsym(pd.procsym);
-              end
-            else
-              unitinits.emit_tai(Tai_const.Create_nil_codeptr,voidcodepointertype);
-            pd := tabstractrecorddef(structlist[i]).find_procdef_bytype(potype_class_destructor);
-            if assigned(pd) then
-              begin
-                unitinits.emit_procdef_const(pd);
-                if u<>current_module then
-                  current_module.addimportedsym(pd.procsym);
-              end
-            else
-              unitinits.emit_tai(Tai_const.Create_nil_codeptr,voidcodepointertype);
-            inc(count);
-          end;
-          structlist.free;
+          new(entry);
+          entry^.module:=current_module;
+          entry^.initpd:=nil;
+          entry^.finipd:=nil;
+          if (current_module.flags and uf_init)<>0 then
+            entry^.initfunc:=make_mangledname('INIT$',current_module.localsymtable,'')
+          else
+            entry^.initfunc:='';
+          if (current_module.flags and uf_finalize)<>0 then
+            entry^.finifunc:=make_mangledname('FINALIZE$',current_module.localsymtable,'')
+          else
+            entry^.finifunc:='';
+          result.add(entry);
         end;
+    end;
+
+
+  class procedure tnodeutils.release_init_final_list(list:tfplist);
+    var
+      i : longint;
+    begin
+      if not assigned(list) then
+        internalerror(2017051901);
+      for i:=0 to list.count-1 do
+        dispose(pinitfinalentry(list[i]));
+      list.free;
+    end;
+
+
+  class procedure tnodeutils.InsertInitFinalTable;
+    var
+      i : longint;
+      unitinits : ttai_typedconstbuilder;
+      nameinit,namefini : TSymStr;
+      tabledef: tdef;
+      entries : tfplist;
+      entry : pinitfinalentry;
 
       procedure add_initfinal_import(symtable:tsymtable);
         var
@@ -979,72 +1069,65 @@ implementation
       unitinits.begin_anonymous_record('',default_settings.packrecords,sizeof(pint),
         targetinfos[target_info.system]^.alignment.recordalignmin,
         targetinfos[target_info.system]^.alignment.maxCrecordalign);
-      { placeholder for tablecount }
-      tablecountplaceholder:=unitinits.emit_placeholder(aluuinttype);
+
+      entries:=get_init_final_list;
+      { tablecount }
+      unitinits.emit_ord_const(entries.count,aluuinttype);
       { initcount (initialised at run time }
       unitinits.emit_ord_const(0,aluuinttype);
-      count:=0;
-      hp:=tused_unit(usedunits.first);
-      while assigned(hp) do
-       begin
-         { insert class constructors/destructors of the unit }
-         if (hp.u.flags and uf_classinits) <> 0 then
-           write_struct_inits(hp.u);
-         { call the unit init code and make it external }
-         if (hp.u.flags and (uf_init or uf_finalize))<>0 then
-           begin
-             if count=high(aint) then
-               Message1(cg_f_max_units_reached,tostr(count));
-             nameinit:='';
-             namefini:='';
-             if (hp.u.flags and uf_init)<>0 then
-               begin
-                 nameinit:=make_mangledname('INIT$',hp.u.globalsymtable,'');
-                 unitinits.emit_tai(
-                   Tai_const.Createname(nameinit,AT_FUNCTION,0),
-                   voidcodepointertype);
-               end
-             else
-               unitinits.emit_tai(Tai_const.Create_nil_codeptr,voidcodepointertype);
-             if (hp.u.flags and uf_finalize)<>0 then
-               begin
-                 namefini:=make_mangledname('FINALIZE$',hp.u.globalsymtable,'');
-                 unitinits.emit_tai(
-                   Tai_const.Createname(namefini,AT_FUNCTION,0),
-                   voidcodepointertype)
-               end
-             else
-               unitinits.emit_tai(Tai_const.Create_nil_codeptr,voidcodepointertype);
-             add_initfinal_import(hp.u.localsymtable);
-             inc(count);
-           end;
-         hp:=tused_unit(hp.next);
-       end;
-      { insert class constructors/destructor of the program }
-      if (current_module.flags and uf_classinits) <> 0 then
-        write_struct_inits(current_module);
-      { Insert initialization/finalization of the program }
-      if (current_module.flags and (uf_init or uf_finalize))<>0 then
+
+      for i:=0 to entries.count-1 do
         begin
-          if (current_module.flags and uf_init)<>0 then
-            unitinits.emit_tai(
-              Tai_const.Createname(make_mangledname('INIT$',current_module.localsymtable,''),AT_FUNCTION,0),
-              voidcodepointertype)
-          else
-            unitinits.emit_tai(Tai_const.Create_nil_codeptr,voidcodepointertype);
-          if (current_module.flags and uf_finalize)<>0 then
-            unitinits.emit_tai(
-              Tai_const.Createname(make_mangledname('FINALIZE$',current_module.localsymtable,''),AT_FUNCTION,0),
-              voidcodepointertype)
+          entry:=pinitfinalentry(entries[i]);
+          if assigned(entry^.initpd) or assigned(entry^.finipd) then
+            begin
+              if assigned(entry^.initpd) then
+                begin
+                  unitinits.emit_procdef_const(entry^.initpd);
+                  if entry^.module<>current_module then
+                    current_module.addimportedsym(entry^.initpd.procsym);
+                end
+              else
+                unitinits.emit_tai(Tai_const.Create_nil_codeptr,voidcodepointertype);
+              if assigned(entry^.finipd) then
+                begin
+                  unitinits.emit_procdef_const(entry^.finipd);
+                  if entry^.module<>current_module then
+                    current_module.addimportedsym(entry^.finipd.procsym);
+                end
+              else
+                unitinits.emit_tai(Tai_const.Create_nil_codeptr,voidcodepointertype);
+            end
           else
-            unitinits.emit_tai(Tai_const.Create_nil_codeptr,voidcodepointertype);
-          inc(count);
+            begin
+              nameinit:='';
+              namefini:='';
+              if entry^.initfunc<>'' then
+                begin
+                  nameinit:=entry^.initfunc;
+                  unitinits.emit_tai(
+                    Tai_const.Createname(nameinit,AT_FUNCTION,0),
+                    voidcodepointertype);
+                end
+              else
+                unitinits.emit_tai(Tai_const.Create_nil_codeptr,voidcodepointertype);
+              if entry^.finifunc<>'' then
+                begin
+                  namefini:=entry^.finifunc;
+                  unitinits.emit_tai(
+                    Tai_const.Createname(namefini,AT_FUNCTION,0),
+                    voidcodepointertype);
+                end
+              else
+                unitinits.emit_tai(Tai_const.Create_nil_codeptr,voidcodepointertype);
+              if entry^.module<>current_module then
+                add_initfinal_import(entry^.module.localsymtable);
+            end;
         end;
-      { fill in tablecount }
-      tablecountplaceholder.replace(tai_const.Create_aint(count),aluuinttype);
-      tablecountplaceholder.free;
-      { Add to data segment }
 
+      release_init_final_list(entries);
+
+      { Add to data segment }
       tabledef:=unitinits.end_anonymous_record;
       current_asmdata.asmlists[al_globals].concatlist(
         unitinits.get_final_asmlist(