Bläddra i källkod

* init/final of procedure data splitted from genentrycode
* use asmnode getposition to insert final at the correct position
als for the implicit try...finally

peter 22 år sedan
förälder
incheckning
77d641fa2a
7 ändrade filer med 367 tillägg och 350 borttagningar
  1. 16 45
      compiler/cgbase.pas
  2. 10 7
      compiler/ncgcal.pas
  3. 17 12
      compiler/ncgflw.pas
  4. 247 229
      compiler/ncgutil.pas
  5. 8 3
      compiler/pass_2.pas
  6. 10 10
      compiler/pmodules.pas
  7. 59 44
      compiler/psub.pas

+ 16 - 45
compiler/cgbase.pas

@@ -89,31 +89,6 @@ unit cgbase;
           {# register used as frame pointer }
           framepointer : tregister;
 
-          {# Holds the environment reference for default exceptions
-
-             The exception reference is created when ansistrings
-             or classes are used. It holds buffer for exception
-             frames. It is allocted by g_new_exception.
-          }
-          exception_env_ref : treference;
-          {# Holds the environment reference for default exceptions
-
-             The exception reference is created when ansistrings
-             or classes are used. It holds buffer for setjmp
-             It is allocted by g_new_exception.
-          }
-          exception_jmp_ref :treference;
-          {# Holds the environment reference for default exceptions
-
-             The exception reference is created when ansistrings
-             or classes are used. It holds the location where
-             temporary storage of the setjmp result is stored.
-
-             This reference can be unused, if the result is instead
-             saved on the stack.
-          }
-          exception_result_ref :treference;
-
           {# Holds the reference used to store the original stackpointer
              after all registers are saved
           }
@@ -125,16 +100,15 @@ unit cgbase;
              systems
           }
           save_regs_ref : treference;
+
+          { label to leave the sub routine }
+          aktexitlabel : tasmlabel;
+
           {# The code for the routine itself, excluding entry and
              exit code. This is a linked list of tai classes.
           }
           aktproccode : taasmoutput;
-          {# The code for the routine entry code.
-          }
-          aktentrycode: taasmoutput;
-          {# The code for the routine exit code.
-          }
-          aktexitcode: taasmoutput;
+          { Data (like jump tables) that belongs to this routine }
           aktlocaldata : taasmoutput;
 
           constructor create(aparent:tprocinfo);virtual;
@@ -183,9 +157,6 @@ unit cgbase;
        { label when the result is true or false }
        truelabel,falselabel : tasmlabel;
 
-       { label to leave the sub routine }
-       aktexitlabel : tasmlabel;
-
        {# true, if there was an error while code generation occurs }
        codegenerror : boolean;
 
@@ -349,26 +320,22 @@ implementation
         flags:=[];
         framepointer.enum:=R_INTREGISTER;
         framepointer.number:=NR_FRAME_POINTER_REG;
-
-        aktentrycode:=Taasmoutput.Create;
-        aktexitcode:=Taasmoutput.Create;
+        { asmlists }
         aktproccode:=Taasmoutput.Create;
         aktlocaldata:=Taasmoutput.Create;
-        reference_reset(exception_env_ref);
-        reference_reset(exception_jmp_ref);
-        reference_reset(exception_result_ref);
         reference_reset(save_stackptr_ref);
+        { labels }
+        objectlibrary.getlabel(aktexitlabel);
       end;
 
 
     destructor tprocinfo.destroy;
       begin
-         aktentrycode.free;
-         aktexitcode.free;
          aktproccode.free;
          aktlocaldata.free;
       end;
 
+
     procedure tprocinfo.allocate_interrupt_stackframe;
       begin
       end;
@@ -408,8 +375,6 @@ implementation
 
 
     procedure tprocinfo.after_header;
-      var
-        srsym : tvarsym;
       begin
       end;
 
@@ -531,6 +496,7 @@ implementation
         end;
       end;
 
+
     function int_cgsize(const a: aword): tcgsize;
       begin
         if a > 8 then
@@ -573,7 +539,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.53  2003-06-02 21:42:05  jonas
+  Revision 1.54  2003-06-09 12:23:29  peter
+    * init/final of procedure data splitted from genentrycode
+    * use asmnode getposition to insert final at the correct position
+      als for the implicit try...finally
+
+  Revision 1.53  2003/06/02 21:42:05  jonas
     * function results can now also be regvars
     - removed tprocinfo.return_offset, never use it again since it's invalid
       if the result is a regvar

+ 10 - 7
compiler/ncgcal.pas

@@ -1040,10 +1040,10 @@ implementation
          oldprocinfo : tprocinfo;
          oldinlining_procedure : boolean;
          inlineentrycode,inlineexitcode : TAAsmoutput;
-         oldexitlabel:tasmlabel;
          oldregstate: pointer;
          old_local_fixup,
          old_para_fixup : longint;
+         usesacc,usesacchi,usesfpu : boolean;
          pararef,
          localsref : treference;
 {$ifdef GDB}
@@ -1056,10 +1056,8 @@ implementation
            internalerror(200305262);
 
          oldinlining_procedure:=inlining_procedure;
-         oldexitlabel:=aktexitlabel;
          oldprocdef:=current_procdef;
          oldprocinfo:=current_procinfo;
-         objectlibrary.getlabel(aktexitlabel);
          { we're inlining a procedure }
          inlining_procedure:=true;
 
@@ -1258,7 +1256,7 @@ implementation
          inlineentrycode:=TAAsmoutput.Create;
          inlineexitcode:=TAAsmoutput.Create;
 
-         geninlineentrycode(inlineentrycode,0);
+         gen_initialize_code(inlineentrycode,true);
          if po_assembler in current_procdef.procoptions then
            inlineentrycode.insert(Tai_marker.Create(asmblockstart));
          exprasmList.concatlist(inlineentrycode);
@@ -1279,7 +1277,8 @@ implementation
          testregisters32;
 {$endif TEMPREGDEBUG}
 
-         geninlineexitcode(inlineexitcode,true);
+         gen_finalize_code(inlineexitcode,true);
+         gen_load_return_value(inlineexitcode,usesacc,usesacchi,usesfpu);
          if po_assembler in current_procdef.procoptions then
            inlineexitcode.concat(Tai_marker.Create(asmblockend));
          exprasmList.concatlist(inlineexitcode);
@@ -1383,7 +1382,6 @@ implementation
 
          { restore }
          current_procdef:=oldprocdef;
-         aktexitlabel:=oldexitlabel;
          inlining_procedure:=oldinlining_procedure;
 
          { reallocate the registers used for the current procedure's regvars, }
@@ -1409,7 +1407,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.88  2003-06-08 20:01:53  jonas
+  Revision 1.89  2003-06-09 12:23:29  peter
+    * init/final of procedure data splitted from genentrycode
+    * use asmnode getposition to insert final at the correct position
+      als for the implicit try...finally
+
+  Revision 1.88  2003/06/08 20:01:53  jonas
     * optimized assignments with on the right side a function that returns
       an ansi- or widestring
 

+ 17 - 12
compiler/ncgflw.pas

@@ -719,7 +719,7 @@ implementation
          if assigned(left) then
            secondpass(left);
 
-         cg.a_jmp_always(exprasmlist,aktexitlabel);
+         cg.a_jmp_always(exprasmlist,current_procinfo.aktexitlabel);
        end;
 
 
@@ -935,7 +935,7 @@ implementation
          oldendexceptlabel:=endexceptlabel;
 
          { save the old labels for control flow statements }
-         oldaktexitlabel:=aktexitlabel;
+         oldaktexitlabel:=current_procinfo.aktexitlabel;
          if assigned(aktbreaklabel) then
            begin
               oldaktcontinuelabel:=aktcontinuelabel;
@@ -962,7 +962,7 @@ implementation
 
          { try block }
          { set control flow labels for the try block }
-         aktexitlabel:=exittrylabel;
+         current_procinfo.aktexitlabel:=exittrylabel;
          if assigned(oldaktbreaklabel) then
           begin
             aktcontinuelabel:=continuetrylabel;
@@ -983,7 +983,7 @@ implementation
 
          { set control flow labels for the except block }
          { and the on statements                        }
-         aktexitlabel:=exitexceptlabel;
+         current_procinfo.aktexitlabel:=exitexceptlabel;
          if assigned(oldaktbreaklabel) then
           begin
             aktcontinuelabel:=continueexceptlabel;
@@ -1108,7 +1108,7 @@ implementation
          endexceptlabel:=oldendexceptlabel;
 
          { restore the control flow labels }
-         aktexitlabel:=oldaktexitlabel;
+         current_procinfo.aktexitlabel:=oldaktexitlabel;
          if assigned(oldaktbreaklabel) then
           begin
             aktcontinuelabel:=oldaktcontinuelabel;
@@ -1173,9 +1173,9 @@ implementation
 
          if assigned(right) then
            begin
-              oldaktexitlabel:=aktexitlabel;
+              oldaktexitlabel:=current_procinfo.aktexitlabel;
               objectlibrary.getlabel(exitonlabel);
-              aktexitlabel:=exitonlabel;
+              current_procinfo.aktexitlabel:=exitonlabel;
               if assigned(aktbreaklabel) then
                begin
                  oldaktcontinuelabel:=aktcontinuelabel;
@@ -1231,7 +1231,7 @@ implementation
                    cg.a_jmp_always(exprasmlist,oldaktcontinuelabel);
                 end;
 
-              aktexitlabel:=oldaktexitlabel;
+              current_procinfo.aktexitlabel:=oldaktexitlabel;
               if assigned(oldaktbreaklabel) then
                begin
                  aktcontinuelabel:=oldaktcontinuelabel;
@@ -1284,12 +1284,12 @@ implementation
 
          { the finally block must catch break, continue and exit }
          { statements                                            }
-         oldaktexitlabel:=aktexitlabel;
+         oldaktexitlabel:=current_procinfo.aktexitlabel;
          if implicitframe then
            exitfinallylabel:=finallylabel
          else
            objectlibrary.getlabel(exitfinallylabel);
-         aktexitlabel:=exitfinallylabel;
+         current_procinfo.aktexitlabel:=exitfinallylabel;
          if assigned(aktbreaklabel) then
           begin
             oldaktcontinuelabel:=aktcontinuelabel;
@@ -1401,7 +1401,7 @@ implementation
            end;
          cg.a_label(exprasmlist,endfinallylabel);
 
-         aktexitlabel:=oldaktexitlabel;
+         current_procinfo.aktexitlabel:=oldaktexitlabel;
          if assigned(aktbreaklabel) then
           begin
             aktcontinuelabel:=oldaktcontinuelabel;
@@ -1427,7 +1427,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.69  2003-06-07 18:57:04  jonas
+  Revision 1.70  2003-06-09 12:23:30  peter
+    * init/final of procedure data splitted from genentrycode
+    * use asmnode getposition to insert final at the correct position
+      als for the implicit try...finally
+
+  Revision 1.69  2003/06/07 18:57:04  jonas
     + added freeintparaloc
     * ppc get/freeintparaloc now check whether the parameter regs are
       properly allocated/deallocated (and get an extra list para)

+ 247 - 229
compiler/ncgutil.pas

@@ -63,12 +63,18 @@ interface
                               para_offset:longint;alignment : longint;
                               const locpara : tparalocation);
 
-    procedure genentrycode(list:TAAsmoutput;inlined:boolean);
+    procedure gen_load_return_value(list:TAAsmoutput; var uses_acc,uses_acchi,uses_fpu : boolean);
+    procedure gen_initialize_code(list:TAAsmoutput;inlined:boolean);
+    procedure gen_finalize_code(list : TAAsmoutput;inlined:boolean);
+
+    procedure gen_entry_code(list:TAAsmoutput;inlined:boolean);
     procedure gen_stackalloc_code(list:Taasmoutput;stackframe:longint);
-    procedure genexitcode(list:Taasmoutput;inlined:boolean);
+    procedure gen_exit_code(list:Taasmoutput;inlined:boolean);
 
+(*
     procedure geninlineentrycode(list : TAAsmoutput;stackframe:longint);
     procedure geninlineexitcode(list : TAAsmoutput;inlined:boolean);
+*)
 
    {#
       Allocate the buffers for exception management and setjmp environment.
@@ -993,7 +999,7 @@ implementation
 
 
 {****************************************************************************
-                                 Entry/Exit Code
+                            Init/Finalize Code
 ****************************************************************************}
 
     procedure copyvalueparas(p : tnamedindexitem;arg:pointer);
@@ -1147,6 +1153,7 @@ implementation
          end;
       end;
 
+
     { generates the code for decrementing the reference count of parameters }
     procedure final_paras(p : tnamedindexitem;arg:pointer);
       var
@@ -1256,40 +1263,103 @@ implementation
       end;
 
 
-    procedure load_return_value(list:TAAsmoutput; var uses_acc,uses_acchi,uses_fpu : boolean);
+    procedure gen_load_return_value(list:TAAsmoutput; var uses_acc,uses_acchi,uses_fpu : boolean);
       var
-        ressym: tvarsym;
-        resloc: tlocation;
+        ressym : tvarsym;
+        resloc : tlocation;
+        href   : treference;
         hreg,r,r2 : tregister;
       begin
-        if not is_void(current_procdef.rettype.def) then
-         begin
-           ressym := tvarsym(current_procdef.funcretsym);
-           if ressym.reg.enum <> R_NO then
-             begin
-               if paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
-                 location_reset(resloc,LOC_CREGISTER,OS_ADDR)
-               else
-                 if ressym.vartype.def.deftype = floatdef then
-                   location_reset(resloc,LOC_CFPUREGISTER,def_cgsize(current_procdef.rettype.def))
-                 else
-                   location_reset(resloc,LOC_CREGISTER,def_cgsize(current_procdef.rettype.def));
-               resloc.register := ressym.reg;
-             end
-           else
-             begin
-               location_reset(resloc,LOC_REFERENCE,def_cgsize(current_procdef.rettype.def));
-               reference_reset_base(resloc.reference,current_procinfo.framepointer,tvarsym(current_procdef.funcretsym).adjusted_address);
-             end;
-           { Here, we return the function result. In most architectures, the value is
-             passed into the FUNCTION_RETURN_REG, but in a windowed architecure like sparc a
-             function returns in a register and the caller receives it in an other one }
-           case current_procdef.rettype.def.deftype of
-             orddef,
-             enumdef :
+        { Is the loading needed? }
+        if is_void(current_procdef.rettype.def) or
+           (
+            (po_assembler in current_procdef.procoptions) and
+            (not(assigned(current_procdef.funcretsym)) or
+             (tvarsym(current_procdef.funcretsym).refcount=0))
+           ) then
+          exit;
+
+        { Constructors need to return self }
+        if (current_procdef.proctypeoption=potype_constructor) then
+          begin
+            r.enum:=R_INTREGISTER;
+            r.number:=NR_FUNCTION_RETURN_REG;
+            cg.a_reg_alloc(list,r);
+            { return the self pointer }
+            ressym:=tvarsym(current_procdef.parast.search('self'));
+            if not assigned(ressym) then
+              internalerror(200305058);
+            reference_reset_base(href,current_procinfo.framepointer,tvarsym(ressym).adjusted_address);
+            cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,r);
+            cg.a_reg_dealloc(list,r);
+            uses_acc:=true;
+            exit;
+          end;
+
+        ressym := tvarsym(current_procdef.funcretsym);
+        if ressym.reg.enum <> R_NO then
+          begin
+            if paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
+              location_reset(resloc,LOC_CREGISTER,OS_ADDR)
+            else
+              if ressym.vartype.def.deftype = floatdef then
+                location_reset(resloc,LOC_CFPUREGISTER,def_cgsize(current_procdef.rettype.def))
+              else
+                location_reset(resloc,LOC_CREGISTER,def_cgsize(current_procdef.rettype.def));
+            resloc.register := ressym.reg;
+          end
+        else
+          begin
+            location_reset(resloc,LOC_REFERENCE,def_cgsize(current_procdef.rettype.def));
+            reference_reset_base(resloc.reference,current_procinfo.framepointer,tvarsym(current_procdef.funcretsym).adjusted_address);
+          end;
+        { Here, we return the function result. In most architectures, the value is
+          passed into the FUNCTION_RETURN_REG, but in a windowed architecure like sparc a
+          function returns in a register and the caller receives it in an other one }
+        case current_procdef.rettype.def.deftype of
+          orddef,
+          enumdef :
+            begin
+              uses_acc:=true;
+{$ifndef cpu64bit}
+              if resloc.size in [OS_64,OS_S64] then
+               begin
+                 uses_acchi:=true;
+                 r.enum:=R_INTREGISTER;
+                 r.number:=NR_FUNCTION_RETURN64_LOW_REG;
+                 cg.a_reg_alloc(list,r);
+                 r2.enum:=R_INTREGISTER;
+                 r2.number:=NR_FUNCTION_RETURN64_HIGH_REG;
+                 cg.a_reg_alloc(list,r2);
+                 cg64.a_load64_loc_reg(list,resloc,joinreg64(r,r2){$ifdef newra},false{$endif});
+               end
+              else
+{$endif cpu64bit}
+               begin
+                 hreg.enum:=R_INTREGISTER;
+                 hreg.number:=NR_FUNCTION_RETURN_REG;
+                 hreg:=rg.makeregsize(hreg,resloc.size);
+                 cg.a_load_loc_reg(list,resloc.size,resloc,hreg);
+               end;
+            end;
+          floatdef :
+            begin
+              uses_fpu := true;
+{$ifdef cpufpemu}
+               if cs_fp_emulation in aktmoduleswitches then
+                 r.enum := FUNCTION_RETURN_REG
+              else
+{$endif cpufpemu}
+               r.enum:=FPU_RESULT_REG;
+              cg.a_loadfpu_loc_reg(list,resloc,r);
+            end;
+          else
+            begin
+              if not paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
                begin
                  uses_acc:=true;
 {$ifndef cpu64bit}
+                 { Win32 can return records in EAX:EDX }
                  if resloc.size in [OS_64,OS_S64] then
                   begin
                     uses_acchi:=true;
@@ -1305,56 +1375,147 @@ implementation
 {$endif cpu64bit}
                   begin
                     hreg.enum:=R_INTREGISTER;
-                    hreg.number:=NR_FUNCTION_RETURN_REG;
-                    hreg:=rg.makeregsize(hreg,resloc.size);
+                    hreg.number:=(RS_FUNCTION_RETURN_REG shl 8) or cgsize2subreg(resloc.size);
                     cg.a_load_loc_reg(list,resloc.size,resloc,hreg);
                   end;
-               end;
-             floatdef :
-               begin
-                 uses_fpu := true;
-{$ifdef cpufpemu}
-                  if cs_fp_emulation in aktmoduleswitches then
-                    r.enum := FUNCTION_RETURN_REG
-                 else
-{$endif cpufpemu}
-                  r.enum:=FPU_RESULT_REG;
-                 cg.a_loadfpu_loc_reg(list,resloc,r);
-               end;
-             else
+                end
+            end;
+        end;
+      end;
+
+
+    procedure gen_initialize_code(list:TAAsmoutput;inlined:boolean);
+      var
+        href : treference;
+      begin
+        { the actual profile code can clobber some registers,
+          therefore if the context must be saved, do it before
+          the actual call to the profile code
+        }
+        if (cs_profile in aktmoduleswitches) and
+           not(po_assembler in current_procdef.procoptions) and
+           not(inlined) then
+          begin
+            { non-win32 can call mcout even in main }
+            if not (target_info.system in [system_i386_win32,system_i386_wdosx])  then
+              cg.g_profilecode(list)
+            else
+            { wdosx, and win32 should not call mcount before monstartup has been called }
+            if not (current_procdef.proctypeoption=potype_proginit) then
+              cg.g_profilecode(list);
+          end;
+
+        { initialize return value }
+        initretvalue(list);
+
+        { initialize local data like ansistrings }
+        case current_procdef.proctypeoption of
+           potype_unitinit:
+             begin
+                { this is also used for initialization of variables in a
+                  program which does not have a globalsymtable }
+                if assigned(current_module.globalsymtable) then
+                  tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
+                tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
+             end;
+           { units have seperate code for initilization and finalization }
+           potype_unitfinalize: ;
+           { program init/final is generated in separate procedure }
+           potype_proginit: ;
+           else
+             current_procdef.localst.foreach_static({$ifndef TP}@{$endif}initialize_data,list);
+        end;
+
+        { initialisizes temp. ansi/wide string data }
+        inittempvariables(list);
+
+        { generate copies of call by value parameters, must be done before
+          the initialization because the refcounts are incremented using
+          the local copies }
+        if not(po_assembler in current_procdef.procoptions) then
+          current_procdef.parast.foreach_static({$ifndef TP}@{$endif}copyvalueparas,list);
+
+        { initialize ansi/widesstring para's }
+        current_procdef.parast.foreach_static({$ifndef TP}@{$endif}init_paras,list);
+
+        if (not inlined) then
+         begin
+           { call startup helpers from main program }
+           if (current_procdef.proctypeoption=potype_proginit) then
+            begin
+              { initialize profiling for win32 }
+              if (target_info.system in [system_i386_win32,system_i386_wdosx]) and
+                 (cs_profile in aktmoduleswitches) then
                begin
-                 if not paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
-                  begin
-                    uses_acc:=true;
-{$ifndef cpu64bit}
-                    { Win32 can return records in EAX:EDX }
-                    if resloc.size in [OS_64,OS_S64] then
-                     begin
-                       uses_acchi:=true;
-                       r.enum:=R_INTREGISTER;
-                       r.number:=NR_FUNCTION_RETURN64_LOW_REG;
-                       cg.a_reg_alloc(list,r);
-                       r2.enum:=R_INTREGISTER;
-                       r2.number:=NR_FUNCTION_RETURN64_HIGH_REG;
-                       cg.a_reg_alloc(list,r2);
-                       cg64.a_load64_loc_reg(list,resloc,joinreg64(r,r2){$ifdef newra},false{$endif});
-                     end
-                    else
-{$endif cpu64bit}
-                     begin
-                       hreg.enum:=R_INTREGISTER;
-                       hreg.number:=(RS_FUNCTION_RETURN_REG shl 8) or cgsize2subreg(resloc.size);
-                       cg.a_load_loc_reg(list,resloc.size,resloc,hreg);
-                     end;
-                   end
+                 reference_reset_symbol(href,objectlibrary.newasmsymboldata('etext'),0);
+                 cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(list,2));
+                 reference_reset_symbol(href,objectlibrary.newasmsymboldata('__image_base__'),0);
+                 cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(list,1));
+                 cg.a_call_name(list,'_monstartup');
+                 paramanager.freeintparaloc(list,2);
+                 paramanager.freeintparaloc(list,1);
                end;
-           end;
+
+              { initialize units }
+              cg.a_call_name(list,'FPC_INITIALIZEUNITS');
+            end;
+
+{$ifdef GDB}
+           if (cs_debuginfo in aktmoduleswitches) then
+            list.concat(Tai_force_line.Create);
+{$endif GDB}
          end;
+
+        load_regvars(list,nil);
+      end;
+
+
+    procedure gen_finalize_code(list : TAAsmoutput;inlined:boolean);
+      begin
+        cg.a_label(list,current_procinfo.aktexitlabel);
+
+        cleanup_regvars(list);
+
+        { finalize temporary data }
+        finalizetempvariables(list);
+
+        { finalize local data like ansistrings}
+        case current_procdef.proctypeoption of
+           potype_unitfinalize:
+             begin
+                { this is also used for initialization of variables in a
+                  program which does not have a globalsymtable }
+                if assigned(current_module.globalsymtable) then
+                  tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
+                tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
+             end;
+           { units/progs have separate code for initialization and finalization }
+           potype_unitinit: ;
+           { program init/final is generated in separate procedure }
+           potype_proginit: ;
+           else
+             current_procdef.localst.foreach_static({$ifndef TP}@{$endif}finalize_data,list);
+        end;
+
+        { finalize paras data }
+        if assigned(current_procdef.parast) then
+          current_procdef.parast.foreach_static({$ifndef TP}@{$endif}final_paras,list);
+
+        { call __EXIT for main program }
+        if (not DLLsource) and
+           (not inlined) and
+           (current_procdef.proctypeoption=potype_proginit) then
+          cg.a_call_name(list,'FPC_DO_EXIT');
+
+        cleanup_regvars(list);
       end;
 
 
+{****************************************************************************
+                                Entry/Exit
+****************************************************************************}
 
-    procedure genentrycode(list:TAAsmoutput;inlined:boolean);
+    procedure gen_entry_code(list:TAAsmoutput;inlined:boolean);
       var
         href : treference;
         hp : tparaitem;
@@ -1367,7 +1528,6 @@ implementation
 
         if assigned(current_procdef.parast) then
           begin
-
              if not (po_assembler in current_procdef.procoptions) then
                begin
                  { move register parameters which aren't regable into memory                               }
@@ -1423,7 +1583,6 @@ implementation
                end;
           end;
 
-
         { for the save all registers we can simply use a pusha,popa which
           push edi,esi,ebp,esp(ignored),ebx,edx,ecx,eax }
         if (po_saveregisters in current_procdef.procoptions) then
@@ -1444,91 +1603,9 @@ implementation
            rsp.number:=NR_STACK_POINTER_REG;
            cg.a_load_reg_ref(list,OS_ADDR,OS_ADDR,rsp,current_procinfo.save_stackptr_ref);
          end;
-
-        { the actual profile code can clobber some registers,
-          therefore if the context must be saved, do it before
-          the actual call to the profile code
-        }
-        if (cs_profile in aktmoduleswitches) and
-           not(po_assembler in current_procdef.procoptions) and
-           not(inlined) then
-          begin
-            { non-win32 can call mcout even in main }
-            if not (target_info.system in [system_i386_win32,system_i386_wdosx])  then
-              cg.g_profilecode(list)
-            else
-            { wdosx, and win32 should not call mcount before monstartup has been called }
-            if not (current_procdef.proctypeoption=potype_proginit) then
-              cg.g_profilecode(list);
-          end;
-
-        { initialize return value }
-        initretvalue(list);
-
-        { initialize local data like ansistrings }
-        case current_procdef.proctypeoption of
-           potype_unitinit:
-             begin
-                { this is also used for initialization of variables in a
-                  program which does not have a globalsymtable }
-                if assigned(current_module.globalsymtable) then
-                  tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
-                tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}initialize_data,list);
-             end;
-           { units have seperate code for initilization and finalization }
-           potype_unitfinalize: ;
-           { program init/final is generated in separate procedure }
-           potype_proginit: ;
-           else
-             current_procdef.localst.foreach_static({$ifndef TP}@{$endif}initialize_data,list);
-        end;
-
-        { initialisizes temp. ansi/wide string data }
-        inittempvariables(list);
-
-        { initialize ansi/widesstring para's }
-        if assigned(current_procdef.parast) then
-          begin
-             current_procdef.parast.foreach_static({$ifndef TP}@{$endif}init_paras,list);
-          end;
-
-        { generate copies of call by value parameters }
-        if not(po_assembler in current_procdef.procoptions) then
-          current_procdef.parast.foreach_static({$ifndef TP}@{$endif}copyvalueparas,list);
-
-        if (not inlined) then
-         begin
-           { call startup helpers from main program }
-           if (current_procdef.proctypeoption=potype_proginit) then
-            begin
-              { initialize profiling for win32 }
-              if (target_info.system in [system_i386_win32,system_i386_wdosx]) and
-                 (cs_profile in aktmoduleswitches) then
-               begin
-                 reference_reset_symbol(href,objectlibrary.newasmsymboldata('etext'),0);
-                 cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(list,2));
-                 reference_reset_symbol(href,objectlibrary.newasmsymboldata('__image_base__'),0);
-                 cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(list,1));
-                 cg.a_call_name(list,'_monstartup');
-                 paramanager.freeintparaloc(list,2);
-                 paramanager.freeintparaloc(list,1);
-               end;
-
-              { initialize units }
-              cg.a_call_name(list,'FPC_INITIALIZEUNITS');
-            end;
-
-{$ifdef GDB}
-           if (cs_debuginfo in aktmoduleswitches) then
-            list.concat(Tai_force_line.Create);
-{$endif GDB}
-         end;
-
-        if inlined then
-          load_regvars(list,nil);
-
       end;
 
+
     procedure gen_stackalloc_code(list:Taasmoutput;stackframe:longint);
 
     var hs:string;
@@ -1600,7 +1677,8 @@ implementation
         end;
     end;
 
-    procedure genexitcode(list : TAAsmoutput;inlined:boolean);
+
+    procedure gen_exit_code(list : TAAsmoutput;inlined:boolean);
 
       var
 {$ifdef GDB}
@@ -1608,82 +1686,18 @@ implementation
         mangled_length : longint;
         p : pchar;
 {$endif GDB}
-        okexitlabel : tasmlabel;
-        href : treference;
-        srsym : tsym;
         usesacc,
         usesacchi,
         usesfpu : boolean;
-        rsp,r : Tregister;
+        rsp : Tregister;
         retsize : longint;
       begin
-        if aktexitlabel.is_used then
-          cg.a_label(list,aktexitlabel);
-
-        cleanup_regvars(list);
-
-        { finalize temporary data }
-        finalizetempvariables(list);
-
-        { finalize local data like ansistrings}
-        case current_procdef.proctypeoption of
-           potype_unitfinalize:
-             begin
-                { this is also used for initialization of variables in a
-                  program which does not have a globalsymtable }
-                if assigned(current_module.globalsymtable) then
-                  tsymtable(current_module.globalsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
-                tsymtable(current_module.localsymtable).foreach_static({$ifndef TP}@{$endif}finalize_data,list);
-             end;
-           { units/progs have separate code for initialization and finalization }
-           potype_unitinit: ;
-           { program init/final is generated in separate procedure }
-           potype_proginit: ;
-           else
-             current_procdef.localst.foreach_static({$ifndef TP}@{$endif}finalize_data,list);
-        end;
-
-        { finalize paras data }
-        if assigned(current_procdef.parast) then
-          current_procdef.parast.foreach_static({$ifndef TP}@{$endif}final_paras,list);
-
-        { call __EXIT for main program }
-        if (not DLLsource) and
-           (not inlined) and
-           (current_procdef.proctypeoption=potype_proginit) then
-         begin
-           cg.a_call_name(list,'FPC_DO_EXIT');
-         end;
-
         { handle return value, this is not done for assembler routines when
           they didn't reference the result variable }
         usesacc:=false;
+        usesfpu:=false;
         usesacchi:=false;
-        if not(po_assembler in current_procdef.procoptions) or
-           (assigned(current_procdef.funcretsym) and
-            (tvarsym(current_procdef.funcretsym).refcount>1)) then
-          begin
-            if (current_procdef.proctypeoption=potype_constructor) then
-              begin
-                objectlibrary.getlabel(okexitlabel);
-                cg.a_jmp_always(list,okexitlabel);
-                { Success exit }
-                cg.a_label(list,okexitlabel);
-                r.enum:=R_INTREGISTER;
-                r.number:=NR_FUNCTION_RETURN_REG;
-                cg.a_reg_alloc(list,r);
-                { return the self pointer }
-                srsym:=tvarsym(current_procdef.parast.search('self'));
-                if not assigned(srsym) then
-                  internalerror(200305058);
-                reference_reset_base(href,current_procinfo.framepointer,tvarsym(srsym).adjusted_address);
-                cg.a_load_ref_reg(list,OS_ADDR,OS_ADDR,href,r);
-                cg.a_reg_dealloc(list,r);
-                usesacc:=true;
-              end
-            else
-              load_return_value(list,usesacc,usesacchi,usesfpu)
-          end;
+        gen_load_return_value(list,usesacc,usesacchi,usesfpu);
 
 {$ifdef GDB}
         if ((cs_debuginfo in aktmoduleswitches) and not inlined) then
@@ -1812,9 +1826,6 @@ implementation
             freemem(p,2*mangled_length+50);
           end;
 {$endif GDB}
-
-        if inlined then
-         cleanup_regvars(list);
       end;
 
 
@@ -1822,6 +1833,7 @@ implementation
                                  Inlining
 ****************************************************************************}
 
+(*
     procedure load_inlined_return_value(list:TAAsmoutput);
       var
         ressym: tvarsym;
@@ -1959,11 +1971,17 @@ implementation
 
         cleanup_regvars(list);
       end;
+*)
 
 end.
 {
   $Log$
-  Revision 1.123  2003-06-07 18:57:04  jonas
+  Revision 1.124  2003-06-09 12:23:30  peter
+    * init/final of procedure data splitted from genentrycode
+    * use asmnode getposition to insert final at the correct position
+      als for the implicit try...finally
+
+  Revision 1.123  2003/06/07 18:57:04  jonas
     + added freeintparaloc
     * ppc get/freeintparaloc now check whether the parameter regs are
       properly allocated/deallocated (and get an extra list para)

+ 8 - 3
compiler/pass_2.pas

@@ -279,13 +279,13 @@ implementation
 
               { process register variable stuff (JM) }
               assign_regvars(p);
-              load_regvars(current_procinfo.aktentrycode,p);
+//              load_regvars(current_procinfo.aktentrycode,p);
 
               { for the i386 it must be done in genexitcode because it has  }
               { to add 'fstp' instructions when using fpu regvars and those }
               { must come after the "exitlabel" (JM)                        }
 {$ifndef i386}
-              cleanup_regvars(current_procinfo.aktexitcode);
+//              cleanup_regvars(current_procinfo.aktexitcode);
 {$endif i386}
 {$ifdef newra}
               if current_procinfo.framepointer.number=NR_EBP then
@@ -309,7 +309,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.54  2003-06-03 13:01:59  daniel
+  Revision 1.55  2003-06-09 12:23:30  peter
+    * init/final of procedure data splitted from genentrycode
+    * use asmnode getposition to insert final at the correct position
+      als for the implicit try...finally
+
+  Revision 1.54  2003/06/03 13:01:59  daniel
     * Register allocator finished
 
   Revision 1.53  2003/05/26 21:17:17  peter

+ 10 - 10
compiler/pmodules.pas

@@ -753,7 +753,6 @@ implementation
     procedure gen_implicit_initfinal(list:taasmoutput;flag:word;st:tsymtable);
       var
         pd : tprocdef;
-        oldexitlabel : tasmlabel;
       begin
         { update module flags }
         current_module.flags:=current_module.flags or flag;
@@ -772,18 +771,14 @@ implementation
           else
             internalerror(200304253);
         end;
-        { save labels }
-        oldexitlabel:=aktexitlabel;
-        { generate a dummy function }
-        objectlibrary.getlabel(aktexitlabel);
         include(current_procinfo.flags,pi_do_call);
         gen_stackalloc_code(list,0);
-        genentrycode(list,false);
-        genexitcode(list,false);
+        gen_entry_code(list,false);
+        gen_initialize_code(list,false);
+        gen_finalize_code(list,false);
+        gen_exit_code(list,false);
         list.convert_registers;
         release_main_proc(pd);
-        { restore }
-        aktexitlabel:=oldexitlabel;
       end;
 
 
@@ -1461,7 +1456,12 @@ So, all parameters are passerd into registers in sparc architecture.}
 end.
 {
   $Log$
-  Revision 1.112  2003-06-07 20:26:32  peter
+  Revision 1.113  2003-06-09 12:23:30  peter
+    * init/final of procedure data splitted from genentrycode
+    * use asmnode getposition to insert final at the correct position
+      als for the implicit try...finally
+
+  Revision 1.112  2003/06/07 20:26:32  peter
     * re-resolving added instead of reloading from ppu
     * tderef object added to store deref info for resolving
 

+ 59 - 44
compiler/psub.pas

@@ -35,6 +35,9 @@ interface
       tcgprocinfo=class(tprocinfo)
         { code for the subroutine as tree }
         code : tnode;
+        { positions in the tree for init/final }
+        initasmnode,
+        finalasmnode : tnode;
         { list to store the procinfo's of the nested procedures }
         nestedprocs : tlinkedlist;
         constructor create(aparent:tprocinfo);override;
@@ -254,6 +257,10 @@ implementation
       begin
         result:=internalstatements(newstatement,true);
 
+        { temp/para/locals initialize code will be inserted here }
+        tcgprocinfo(current_procinfo).initasmnode:=casmnode.create_get_position;
+        addstatement(newstatement,tcgprocinfo(current_procinfo).initasmnode);
+
         if assigned(current_procdef._class) then
           begin
             { a constructor needs a help procedure }
@@ -347,7 +354,9 @@ implementation
 
     function generate_finalize_block:tnode;
       begin
-        result:=cnothingnode.create;
+        { temp/para/locals finalize code will be inserted here }
+        tcgprocinfo(current_procinfo).finalasmnode:=casmnode.create_get_position;
+        result:=tcgprocinfo(current_procinfo).finalasmnode;
       end;
 
 
@@ -557,9 +566,9 @@ implementation
       var
         oldprocdef : tprocdef;
         oldprocinfo : tprocinfo;
-        oldexitlabel : tasmlabel;
         oldaktmaxfpuregisters : longint;
         oldfilepos : tfileposinfo;
+        templist,
         stackalloccode : Taasmoutput;
 
       begin
@@ -577,12 +586,10 @@ implementation
         current_procinfo:=self;
         current_procdef:=procdef;
 
-        { save old labels }
-        oldexitlabel:=aktexitlabel;
         { get new labels }
-        objectlibrary.getlabel(aktexitlabel);
         aktbreaklabel:=nil;
         aktcontinuelabel:=nil;
+        templist:=Taasmoutput.create;
 
         { add parast/localst to symtablestack }
         add_to_symtablestack;
@@ -597,25 +604,34 @@ implementation
       {$endif}
 
         { set the start offset to the start of the temp area in the stack }
-        tg.setfirsttemp(current_procinfo.firsttemp_offset);
+        tg.setfirsttemp(firsttemp_offset);
 
         generatecode(code);
 
-        { first generate entry code with the correct position and switches }
-        aktfilepos:=current_procinfo.entrypos;
-        aktlocalswitches:=current_procinfo.entryswitches;
-        genentrycode(current_procinfo.aktentrycode,false);
-
-        { now generate exit code with the correct position and switches }
-        aktfilepos:=current_procinfo.exitpos;
-        aktlocalswitches:=current_procinfo.exitswitches;
-        genexitcode(current_procinfo.aktexitcode,false);
+        { first generate entry and initialize code with the correct
+          position and switches }
+        aktfilepos:=entrypos;
+        aktlocalswitches:=entryswitches;
+        gen_initialize_code(templist,false);
+        aktproccode.insertlistafter(tasmnode(initasmnode).currenttai,templist);
+        gen_entry_code(templist,false);
+        aktproccode.insertlist(templist);
+
+        { now generate finalize and exit code with the correct position
+          and switches }
+        aktfilepos:=exitpos;
+        aktlocalswitches:=exitswitches;
+        gen_finalize_code(templist,false);
+        { the finalcode must be added if the was no position available,
+          using insertlistafter will result in an insert at the start
+          when currentai=nil }
+        if assigned(tasmnode(finalasmnode).currenttai) then
+          aktproccode.insertlistafter(tasmnode(finalasmnode).currenttai,templist)
+        else
+          aktproccode.concatlist(templist);
+        gen_exit_code(templist,false);
+        aktproccode.concatlist(templist);
 
-        { now all the registers used are known }
-{        current_procdef.usedintregisters:=rg.usedintinproc;
-        current_procdef.usedotherregisters:=rg.usedinproc;}
-        current_procinfo.aktproccode.insertlist(current_procinfo.aktentrycode);
-        current_procinfo.aktproccode.concatlist(current_procinfo.aktexitcode);
 {$ifdef newra}
 {                rg.writegraph;}
 {$endif}
@@ -627,16 +643,16 @@ implementation
               rg.prepare_colouring;
               rg.colour_registers;
               rg.epilogue_colouring;
-            until (rg.spillednodes='') or not rg.spill_registers(current_procinfo.aktproccode,rg.spillednodes);
-            current_procinfo.aktproccode.translate_registers(rg.colour);
-            current_procinfo.aktproccode.convert_registers;
+            until (rg.spillednodes='') or not rg.spill_registers(aktproccode,rg.spillednodes);
+            aktproccode.translate_registers(rg.colour);
+            aktproccode.convert_registers;
 {$else newra}
-            current_procinfo.aktproccode.convert_registers;
+            aktproccode.convert_registers;
 {$ifndef NoOpt}
             if (cs_optimize in aktglobalswitches) and
             { do not optimize pure assembler procedures }
                not(pi_is_assembler in current_procinfo.flags)  then
-              optimize(current_procinfo.aktproccode);
+              optimize(aktproccode);
 {$endif NoOpt}
 {$endif newra}
           end;
@@ -644,31 +660,31 @@ implementation
         stackalloccode:=Taasmoutput.create;
         gen_stackalloc_code(stackalloccode,0);
         stackalloccode.convert_registers;
-        current_procinfo.aktproccode.insertlist(stackalloccode);
+        aktproccode.insertlist(stackalloccode);
         stackalloccode.destroy;
 
         { now all the registers used are known }
         { Remove all imaginary registers from the used list.}
 {$ifdef newra}
-        current_procdef.usedintregisters:=rg.usedintinproc*ALL_INTREGISTERS-rg.savedbyproc;
+        procdef.usedintregisters:=rg.usedintinproc*ALL_INTREGISTERS-rg.savedbyproc;
 {$else}
-        current_procdef.usedintregisters:=rg.usedintinproc;
+        procdef.usedintregisters:=rg.usedintinproc;
 {$endif}
-        current_procdef.usedotherregisters:=rg.usedinproc;
+        procdef.usedotherregisters:=rg.usedinproc;
 
         { save local data (casetable) also in the same file }
-        if assigned(current_procinfo.aktlocaldata) and
-           (not current_procinfo.aktlocaldata.empty) then
+        if assigned(aktlocaldata) and
+           (not aktlocaldata.empty) then
          begin
-           current_procinfo.aktproccode.concat(Tai_section.Create(sec_data));
-           current_procinfo.aktproccode.concatlist(current_procinfo.aktlocaldata);
-           current_procinfo.aktproccode.concat(Tai_section.Create(sec_code));
+           aktproccode.concat(Tai_section.Create(sec_data));
+           aktproccode.concatlist(aktlocaldata);
+           aktproccode.concat(Tai_section.Create(sec_code));
         end;
 
         { add the procedure to the codesegment }
         if (cs_create_smart in aktmoduleswitches) then
-         codesegment.concat(Tai_cut.Create);
-        codesegment.concatlist(current_procinfo.aktproccode);
+          codesegment.concat(Tai_cut.Create);
+        codesegment.concatlist(aktproccode);
 
         { all registers can be used again }
         rg.resetusableregisters;
@@ -678,10 +694,8 @@ implementation
         { restore symtablestack }
         remove_from_symtablestack;
 
-        { restore labels }
-        aktexitlabel:=oldexitlabel;
-
         { restore }
+        templist.free;
         aktmaxfpuregisters:=oldaktmaxfpuregisters;
         aktfilepos:=oldfilepos;
         current_procdef:=oldprocdef;
@@ -770,7 +784,6 @@ implementation
     procedure tcgprocinfo.parse_body;
       var
          oldprocdef : tprocdef;
-         stackalloccode : Taasmoutput;
          oldprocinfo : tprocinfo;
       begin
          oldprocdef:=current_procdef;
@@ -922,9 +935,6 @@ implementation
 
 
     procedure check_init_paras(p:tnamedindexitem;arg:pointer);
-      var
-        vs : tvarsym;
-        pd : tprocdef;
       begin
         if tsym(p).typ<>varsym then
          exit;
@@ -1259,7 +1269,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.124  2003-06-07 19:37:43  jonas
+  Revision 1.125  2003-06-09 12:23:30  peter
+    * init/final of procedure data splitted from genentrycode
+    * use asmnode getposition to insert final at the correct position
+      als for the implicit try...finally
+
+  Revision 1.124  2003/06/07 19:37:43  jonas
     * pi_do_call must always be set for the main program, since it always
       ends with a call to FPC_DO_EXIT