Просмотр исходного кода

* procinlinenode removed
* aktexit2label removed, fast exit removed
+ tcallnode.inlined_pass_2 added

peter 22 лет назад
Родитель
Сommit
047a066711

+ 6 - 4
compiler/cgbase.pas

@@ -188,9 +188,6 @@ unit cgbase;
        { label to leave the sub routine }
        aktexitlabel : tasmlabel;
 
-       { also an exit label, only used we need to clear only the stack }
-       aktexit2label : tasmlabel;
-
        {# true, if there was an error while code generation occurs }
        codegenerror : boolean;
 
@@ -582,7 +579,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.51  2003-05-23 14:27:35  peter
+  Revision 1.52  2003-05-26 21:17:17  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.51  2003/05/23 14:27:35  peter
     * remove some unit dependencies
     * current_procinfo changes to store more info
 

+ 7 - 3
compiler/defcmp.pas

@@ -1180,8 +1180,7 @@ implementation
          if (m_delphi in aktmodeswitches) then
            exclude(po_comp,po_varargs);
          if ((po_comp * def1.procoptions)= (po_comp * def2.procoptions)) and
-            equal_defs(def1.rettype.def,def2.rettype.def) and
-            (def1.para_size(target_info.alignment.paraalign)=def2.para_size(target_info.alignment.paraalign)) then
+            equal_defs(def1.rettype.def,def2.rettype.def) then
           begin
             { return equal type based on the parameters, but a proc->procvar
               is never exact, so map an exact match of the parameters to
@@ -1211,7 +1210,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.25  2003-05-15 18:58:53  peter
+  Revision 1.26  2003-05-26 21:17:17  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.25  2003/05/15 18:58:53  peter
     * removed selfpointer_offset, vmtpointer_offset
     * tvarsym.adjusted_address
     * address in localsymtable is now in the real direction

+ 10 - 5
compiler/i386/daopt386.pas

@@ -456,19 +456,19 @@ begin
   funcResRegs := funcResRegs - [R_EAX,R_EBX,R_ECX,R_EDX,R_ESI];
   funcResReg := reg.enum in funcResRegs;
   hp1 := p;
-  while not(funcResReg and
+{  while not(funcResReg and
             (p.typ = ait_instruction) and
             (Taicpu(p).opcode = A_JMP) and
             (tasmlabel(Taicpu(p).oper[0].sym) = aktexit2label)) and
         getLastInstruction(p, p) And
         not(regInInstruction(reg.enum, p)) Do
-    hp1 := p;
+    hp1 := p; }
   { don't insert a dealloc for registers which contain the function result }
   { if they are followed by a jump to the exit label (for exit(...))       }
-  if not(funcResReg) or
+  {if not(funcResReg) or
      not((hp1.typ = ait_instruction) and
          (Taicpu(hp1).opcode = A_JMP) and
-         (tasmlabel(Taicpu(hp1).oper[0].sym) = aktexit2label)) then
+         (tasmlabel(Taicpu(hp1).oper[0].sym) = aktexit2label)) then }
     begin
       p := tai_regalloc.deAlloc(reg);
       insertLLItem(AsmL, hp1.previous, hp1, p);
@@ -2669,7 +2669,12 @@ End.
 
 {
   $Log$
-  Revision 1.49  2003-04-27 11:21:35  peter
+  Revision 1.50  2003-05-26 21:17:18  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.49  2003/04/27 11:21:35  peter
     * aktprocdef renamed to current_procdef
     * procinfo renamed to current_procinfo
     * procinfo will now be stored in current_module so it can be

+ 10 - 9
compiler/i386/n386cal.pas

@@ -34,7 +34,7 @@ interface
     type
        ti386callnode = class(tcgcallnode)
        protected
-          function  align_parasize(parasize,para_alignment:longint):longint;override;
+          function  align_parasize:longint;override;
           procedure pop_parasize(pop_size:longint);override;
           procedure extra_interrupt_code;override;
        end;
@@ -76,7 +76,7 @@ implementation
       end;
 
 
-    function ti386callnode.align_parasize(parasize,para_alignment:longint):longint;
+    function ti386callnode.align_parasize:longint;
       var
          pop_size : longint;
 {$ifdef OPTALIGN}
@@ -87,12 +87,8 @@ implementation
          rsp : tregister;
       begin
         pop_size:=0;
-        { Old pushedsize aligned on 4 ? }
-        i:=parasize and 3;
-        if i>0 then
-         inc(pop_size,4-i);
         { This parasize aligned on 4 ? }
-        i:=procdefinition.para_size(para_alignment) and 3;
+        i:=procdefinition.parast.datasize and 3;
         if i>0 then
          inc(pop_size,4-i);
         { insert the opcode and update pushedparasize }
@@ -114,7 +110,7 @@ implementation
          if pop_allowed and (cs_align in aktglobalswitches) then
            begin
               pop_esp:=true;
-              push_size:=procdefinition.para_size(para_alignment);
+              push_size:=procdefinition.parast.datasize;
               { !!!! here we have to take care of return type, self
                 and nested procedures
               }
@@ -201,7 +197,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.91  2003-05-22 21:32:29  peter
+  Revision 1.92  2003-05-26 21:17:18  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.91  2003/05/22 21:32:29  peter
     * removed some unit dependencies
 
   Revision 1.90  2003/04/23 14:42:08  daniel

+ 45 - 206
compiler/ncal.pas

@@ -82,6 +82,8 @@ interface
           { function return node, this is used to pass the data for a
             ret_in_param return value }
           funcretnode    : tnode;
+          { inline function body }
+          inlinecode : tnode;
 
           { separately specified resulttype for some compilerprocs (e.g. }
           { you can't have a function with an "array of char" resulttype }
@@ -158,30 +160,12 @@ interface
        end;
        tcallparanodeclass = class of tcallparanode;
 
-       tprocinlinenode = class(tnode)
-          inlinetree : tnode;
-          inlineprocdef : tprocdef;
-          retoffset,para_offset,para_size : longint;
-          constructor create(p:tprocdef);virtual;
-          destructor destroy;override;
-          constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
-          procedure ppuwrite(ppufile:tcompilerppufile);override;
-          procedure derefimpl;override;
-          function getcopy : tnode;override;
-          function det_resulttype : tnode;override;
-          procedure insertintolist(l : tnodelist);override;
-          function pass_1 : tnode;override;
-          function docompare(p: tnode): boolean; override;
-       end;
-       tprocinlinenodeclass = class of tprocinlinenode;
-
     function reverseparameters(p: tcallparanode): tcallparanode;
 
 
     var
        ccallnode : tcallnodeclass;
        ccallparanode : tcallparanodeclass;
-       cprocinlinenode : tprocinlinenodeclass;
 
 implementation
 
@@ -888,6 +872,7 @@ type
          procdefinition:=nil;
          restypeset:=false;
          funcretnode:=nil;
+         inlinecode:=nil;
          paralength:=-1;
       end;
 
@@ -902,6 +887,7 @@ type
          procdefinition:=def;
          restypeset:=false;
          funcretnode:=nil;
+         inlinecode:=nil;
          paralength:=-1;
       end;
 
@@ -916,6 +902,7 @@ type
          procdefinition:=nil;
          restypeset:=false;
          funcretnode:=nil;
+         inlinecode:=nil;
          paralength:=-1;
       end;
 
@@ -974,6 +961,7 @@ type
       begin
          methodpointer.free;
          funcretnode.free;
+         inlinecode.free;
          inherited destroy;
       end;
 
@@ -990,6 +978,7 @@ type
         restypeset:=boolean(ppufile.getbyte);
         methodpointer:=ppuloadnode(ppufile);
         funcretnode:=ppuloadnode(ppufile);
+        inlinecode:=ppuloadnode(ppufile);
       end;
 
 
@@ -1001,6 +990,7 @@ type
         ppufile.putbyte(byte(restypeset));
         ppuwritenode(ppufile,methodpointer);
         ppuwritenode(ppufile,funcretnode);
+        ppuwritenode(ppufile,inlinecode);
       end;
 
 
@@ -1014,6 +1004,8 @@ type
           methodpointer.derefimpl;
         if assigned(funcretnode) then
           funcretnode.derefimpl;
+        if assigned(inlinecode) then
+          inlinecode.derefimpl;
       end;
 
 
@@ -1035,6 +1027,10 @@ type
          n.funcretnode:=funcretnode.getcopy
         else
          n.funcretnode:=nil;
+        if assigned(inlinecode) then
+         n.inlinecode:=inlinecode.getcopy
+        else
+         n.inlinecode:=nil;
         result:=n;
       end;
 
@@ -2270,13 +2266,12 @@ type
 
 
     function tcallnode.pass_1 : tnode;
-      var
-         inlinecode : tnode;
-         inlined : boolean;
 {$ifdef m68k}
+      var
          regi : tregister;
 {$endif}
 {$ifdef callparatemp}
+      var
          callparatemps, newblock: tblocknode;
          statement: tstatementnode;
          paras, oldright, newcall: tnode;
@@ -2285,8 +2280,6 @@ type
         errorexit;
       begin
          result:=nil;
-         inlined:=false;
-         inlinecode := nil;
 
          { work trough all parameters to get the register requirements }
          if assigned(left) then
@@ -2300,15 +2293,6 @@ type
          if assigned(funcretnode) then
            firstpass(funcretnode);
 
-         if assigned(procdefinition) and
-            (procdefinition.proccalloption=pocall_inline) then
-           begin
-              inlinecode:=right;
-              if assigned(inlinecode) then
-               inlined:=true;
-              right:=nil;
-           end;
-
          { procedure variable ? }
          if assigned(right) then
            begin
@@ -2329,22 +2313,20 @@ type
                 begin
                    if assigned(methodpointer) then
                      CGMessage(cg_e_unable_inline_object_methods);
-                   if assigned(right) and (right.nodetype<>procinlinen) then
+                   if assigned(right) then
                      CGMessage(cg_e_unable_inline_procvar);
-                   if not assigned(inlinecode) then
+                   if assigned(inlinecode) then
+                     internalerror(200305261);
+                   if assigned(tprocdef(procdefinition).code) then
+                     inlinecode:=tprocdef(procdefinition).code.getcopy
+                   else
+                     CGMessage(cg_e_no_code_for_inline_stored);
+                   if assigned(inlinecode) then
                      begin
-                        if assigned(tprocdef(procdefinition).code) then
-                          inlinecode:=cprocinlinenode.create(tprocdef(procdefinition))
-                        else
-                          CGMessage(cg_e_no_code_for_inline_stored);
-                        if assigned(inlinecode) then
-                          begin
-                             { consider it has not inlined if called
-                               again inside the args }
-                             procdefinition.proccalloption:=pocall_fpccall;
-                             firstpass(inlinecode);
-                             inlined:=true;
-                          end;
+                       { consider it has not inlined if called
+                         again inside the args }
+                       procdefinition.proccalloption:=pocall_fpccall;
+                       firstpass(inlinecode);
                      end;
                 end
               else
@@ -2356,7 +2338,6 @@ type
              { It doesn't hurt to calculate it already though :) (JM) }
              rg.incrementintregisterpushed(tprocdef(procdefinition).usedintregisters);
              rg.incrementotherregisterpushed(tprocdef(procdefinition).usedotherregisters);
-
            end;
 
          { get a register for the return value }
@@ -2458,8 +2439,16 @@ type
                 verifyabstractcalls;
            end;
 
-         if inlined then
-           right:=inlinecode;
+         { determine the registers of the procedure variable }
+         { is this OK for inlined procs also ?? (PM)     }
+         if assigned(inlinecode) then
+           begin
+              registersfpu:=max(inlinecode.registersfpu,registersfpu);
+              registers32:=max(inlinecode.registers32,registers32);
+{$ifdef SUPPORT_MMX}
+              registersmmx:=max(inlinecode.registersmmx,registersmmx);
+{$endif SUPPORT_MMX}
+           end;
          { determine the registers of the procedure variable }
          { is this OK for inlined procs also ?? (PM)     }
          if assigned(right) then
@@ -2506,7 +2495,7 @@ type
            end;
 {$endif callparatemp}
       errorexit:
-         if inlined then
+         if assigned(inlinecode) then
            procdefinition.proccalloption:=pocall_inline;
 {$ifdef callparatemp}
          if assigned(callparatemps) then
@@ -2574,168 +2563,18 @@ type
       end;
 
 
-{****************************************************************************
-                            TPROCINLINENODE
- ****************************************************************************}
-
-    constructor tprocinlinenode.create(p:tprocdef);
-
-      begin
-         inherited create(procinlinen);
-         inlineprocdef:=p;
-         retoffset:=-POINTER_SIZE; { less dangerous as zero (PM) }
-         para_offset:=0;
-         para_size:=0;
-         { copy inlinetree }
-         if assigned(p.code) then
-           inlinetree:=p.code.getcopy
-         else
-           inlinetree:=nil;
-      end;
-
-
-    destructor tprocinlinenode.destroy;
-      begin
-        if assigned(inlinetree) then
-          inlinetree.free;
-        inherited destroy;
-      end;
-
-
-    constructor tprocinlinenode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
-      begin
-        inherited ppuload(t,ppufile);
-        inlineprocdef:=tprocdef(ppufile.getderef);
-        inlinetree:=ppuloadnode(ppufile);
-        retoffset:=-POINTER_SIZE; { less dangerous as zero (PM) }
-        para_offset:=0;
-        para_size:=0;
-      end;
-
-
-    procedure tprocinlinenode.ppuwrite(ppufile:tcompilerppufile);
-      begin
-        inherited ppuwrite(ppufile);
-        ppufile.putderef(inlineprocdef);
-        ppuwritenode(ppufile,inlinetree);
-      end;
-
-
-    procedure tprocinlinenode.derefimpl;
-      begin
-        inherited derefimpl;
-        if assigned(inlinetree) then
-          inlinetree.derefimpl;
-        resolvedef(pointer(inlineprocdef));
-      end;
-
-
-    function tprocinlinenode.getcopy : tnode;
-
-      var
-         n : tprocinlinenode;
-
-      begin
-         n:=tprocinlinenode(inherited getcopy);
-         n.inlineprocdef:=inlineprocdef;
-         if assigned(inlinetree) then
-           n.inlinetree:=inlinetree.getcopy
-         else
-           n.inlinetree:=nil;
-         n.retoffset:=retoffset;
-         n.para_offset:=para_offset;
-         n.para_size:=para_size;
-         getcopy:=n;
-      end;
-
-    procedure tprocinlinenode.insertintolist(l : tnodelist);
-
-      begin
-      end;
-
-
-    function tprocinlinenode.det_resulttype : tnode;
-      var
-        storesymtablelevel : longint;
-        storeparasymtable,
-        storelocalsymtable : tsymtabletype;
-        oldprocdef : tprocdef;
-        oldprocinfo : tprocinfo;
-        oldinlining_procedure : boolean;
-      begin
-        result:=nil;
-        oldinlining_procedure:=inlining_procedure;
-        oldprocdef:=current_procdef;
-        oldprocinfo:=current_procinfo;
-        { we're inlining a procedure }
-        inlining_procedure:=true;
-
-        { create temp procinfo }
-        current_procinfo:=cprocinfo.create(nil);
-        current_procinfo.procdef:=inlineprocdef;
-        current_procinfo.return_offset:=retoffset;
-        current_procdef:=current_procinfo.procdef;
-
-        { set it to the same lexical level }
-        storesymtablelevel:=current_procdef.localst.symtablelevel;
-        storelocalsymtable:=current_procdef.localst.symtabletype;
-        storeparasymtable:=current_procdef.parast.symtabletype;
-        current_procdef.localst.symtablelevel:=oldprocdef.localst.symtablelevel;
-        current_procdef.localst.symtabletype:=inlinelocalsymtable;
-        current_procdef.parast.symtabletype:=inlineparasymtable;
-
-        { pass inlinetree }
-        resulttypepass(inlinetree);
-        resulttype:=inlineprocdef.rettype;
-
-        { retrieve info from inlineprocdef }
-        retoffset:=-POINTER_SIZE; { less dangerous as zero (PM) }
-        para_offset:=0;
-        para_size:=inlineprocdef.para_size(target_info.alignment.paraalign);
-        if paramanager.ret_in_param(inlineprocdef.rettype.def,inlineprocdef.proccalloption) then
-          inc(para_size,POINTER_SIZE);
-
-        { restore current_procinfo }
-        current_procinfo.free;
-        current_procinfo:=oldprocinfo;
-        { restore symtable }
-        current_procdef.localst.symtablelevel:=storesymtablelevel;
-        current_procdef.localst.symtabletype:=storelocalsymtable;
-        current_procdef.parast.symtabletype:=storeparasymtable;
-        { restore }
-        current_procdef:=oldprocdef;
-        inlining_procedure:=oldinlining_procedure;
-      end;
-
-
-    function tprocinlinenode.pass_1 : tnode;
-      begin
-        firstpass(inlinetree);
-        registers32:=inlinetree.registers32;
-        registersfpu:=inlinetree.registersfpu;
-{$ifdef SUPPORT_MMX}
-        registersmmx:=inlinetree.registersmmx;
-{$endif SUPPORT_MMX}
-        result:=nil;
-      end;
-
-
-    function tprocinlinenode.docompare(p: tnode): boolean;
-      begin
-        docompare :=
-          inherited docompare(p) and
-          inlinetree.isequal(tprocinlinenode(p).inlinetree) and
-          (inlineprocdef = tprocinlinenode(p).inlineprocdef);
-      end;
-
 begin
    ccallnode:=tcallnode;
    ccallparanode:=tcallparanode;
-   cprocinlinenode:=tprocinlinenode;
 end.
 {
   $Log$
-  Revision 1.161  2003-05-25 11:34:17  peter
+  Revision 1.162  2003-05-26 21:17:17  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.161  2003/05/25 11:34:17  peter
     * methodpointer self pushing fixed
 
   Revision 1.160  2003/05/25 08:59:16  peter

+ 446 - 337
compiler/ncgcal.pas

@@ -40,9 +40,13 @@ interface
        end;
 
        tcgcallnode = class(tcallnode)
+       private
+          procedure release_para_temps;
+          procedure normal_pass_2;
+          procedure inlined_pass_2;
        protected
           refcountedtemp : treference;
-          procedure handle_return_value(inlined:boolean);
+          procedure handle_return_value;
           {# This routine is used to push the current frame pointer
              on the stack. This is used in nested routines where the
              value of the frame pointer is always pushed as an extra
@@ -52,7 +56,7 @@ interface
              most stack based machines, where the frame pointer is
              the first invisible parameter.
           }
-          function  align_parasize(parasize,para_alignment:longint):longint;virtual;
+          function  align_parasize:longint;virtual;
           procedure pop_parasize(pop_size:longint);virtual;
           procedure push_framepointer;virtual;
           procedure extra_interrupt_code;virtual;
@@ -60,10 +64,6 @@ interface
           procedure pass_2;override;
        end;
 
-       tcgprocinlinenode = class(tprocinlinenode)
-          procedure pass_2;override;
-       end;
-
 
 implementation
 
@@ -123,12 +123,8 @@ implementation
          { push from left to right if specified }
          if push_from_left_to_right and assigned(right) then
           begin
-            if (nf_varargs_para in flags) then
-              tcallparanode(right).secondcallparan(push_from_left_to_right,
-                                                   calloption,para_alignment,para_offset)
-            else
-              tcallparanode(right).secondcallparan(push_from_left_to_right,
-                                                   calloption,para_alignment,para_offset);
+            tcallparanode(right).secondcallparan(push_from_left_to_right,
+                                                 calloption,para_alignment,para_offset);
           end;
 
          otlabel:=truelabel;
@@ -347,10 +343,6 @@ implementation
          { push from right to left }
          if not push_from_left_to_right and assigned(right) then
           begin
-            if (nf_varargs_para in flags) then
-              tcallparanode(right).secondcallparan(push_from_left_to_right,
-                                                   calloption,para_alignment,para_offset)
-            else
               tcallparanode(right).secondcallparan(push_from_left_to_right,
                                                    calloption,para_alignment,para_offset);
           end;
@@ -366,7 +358,7 @@ implementation
       end;
 
 
-    function tcgcallnode.align_parasize(parasize,para_alignment:longint):longint;
+    function tcgcallnode.align_parasize:longint;
       begin
         result:=0;
       end;
@@ -413,7 +405,7 @@ implementation
       end;
 
 
-    procedure tcgcallnode.handle_return_value(inlined:boolean);
+    procedure tcgcallnode.handle_return_value;
       var
         cgsize : tcgsize;
         r,hregister : tregister;
@@ -465,8 +457,7 @@ implementation
                 cgsize:=def_cgsize(resulttype.def);
 
                 { an object constructor is a function with pointer result }
-                if (inlined or (right=nil)) and
-                   (procdefinition.proctypeoption=potype_constructor) then
+                if (procdefinition.proctypeoption=potype_constructor) then
                   cgsize:=OS_ADDR;
 
                 if cgsize<>OS_NO then
@@ -541,7 +532,41 @@ implementation
       end;
 
 
-    procedure tcgcallnode.pass_2;
+    procedure tcgcallnode.release_para_temps;
+      var
+        hp  : tnode;
+        ppn : tcallparanode;
+      begin
+        { Release temps from parameters }
+        ppn:=tcallparanode(left);
+        while assigned(ppn) do
+          begin
+             if assigned(ppn.left) then
+               begin
+                 { don't release the funcret temp }
+                 if not(vo_is_funcret in tvarsym(ppn.paraitem.parasym).varoptions) then
+                   location_freetemp(exprasmlist,ppn.left.location);
+                 { process also all nodes of an array of const }
+                 if ppn.left.nodetype=arrayconstructorn then
+                   begin
+                     if assigned(tarrayconstructornode(ppn.left).left) then
+                      begin
+                        hp:=ppn.left;
+                        while assigned(hp) do
+                         begin
+                           location_freetemp(exprasmlist,tarrayconstructornode(hp).left.location);
+                           hp:=tarrayconstructornode(hp).right;
+                         end;
+                      end;
+                   end;
+               end;
+             ppn:=tcallparanode(ppn.right);
+          end;
+
+      end;
+
+
+    procedure tcgcallnode.normal_pass_2;
       var
          regs_to_push_int : Tsupregset;
          regs_to_push_other : tregisterset;
@@ -553,23 +578,16 @@ implementation
          iolabel : tasmlabel;
          { help reference pointer }
          href : treference;
-         hp : tnode;
-         pp : tcallparanode;
-         inlined : boolean;
-         inlinecode : tprocinlinenode;
          pushedregs : tmaybesave;
-         store_parast_fixup,
          para_alignment,
-         para_offset : longint;
          pop_size : longint;
-         returnref,
-         pararef : treference;
          accreg : tregister;
          oldaktcallnode : tcallnode;
       begin
+         if not assigned(procdefinition) then
+           internalerror(200305264);
+
          iolabel:=nil;
-         inlinecode:=nil;
-         inlined:=false;
          rg.saveunusedstate(unusedstate);
 
          { if we allocate the temp. location for ansi- or widestrings }
@@ -590,38 +608,8 @@ implementation
          else
           para_alignment:=aktalignment.paraalign;
 
-         if not assigned(procdefinition) then
-          exit;
-
-         if (procdefinition.proccalloption=pocall_inline) then
-           begin
-              inlined:=true;
-              inlinecode:=tprocinlinenode(right);
-              right:=nil;
-              { set it to the same lexical level as the local symtable, becuase
-                the para's are stored there }
-              tprocdef(procdefinition).parast.symtablelevel:=current_procdef.localst.symtablelevel;
-              if assigned(left) then
-               begin
-                 inlinecode.para_size:=tprocdef(procdefinition).para_size(para_alignment);
-                 tg.GetTemp(exprasmlist,inlinecode.para_size,tt_persistent,pararef);
-                 inlinecode.para_offset:=pararef.offset;
-               end;
-              store_parast_fixup:=tprocdef(procdefinition).parast.address_fixup;
-              tprocdef(procdefinition).parast.address_fixup:=inlinecode.para_offset;
-{$ifdef extdebug}
-             Comment(V_debug,
-               'inlined parasymtable is at offset '
-               +tostr(tprocdef(procdefinition).parast.address_fixup));
-             exprasmList.concat(tai_comment.Create(
-               strpnew('inlined parasymtable is at offset '
-               +tostr(tprocdef(procdefinition).parast.address_fixup))));
-{$endif extdebug}
-           end;
-
          { proc variables destroy all registers }
-         if (inlined or
-            (right=nil)) and
+         if (right=nil) and
             { virtual methods too }
             not(po_virtualmethod in procdefinition.procoptions) then
            begin
@@ -669,11 +657,9 @@ implementation
          { Initialize for pushing the parameters }
          oldpushedparasize:=pushedparasize;
          pushedparasize:=0;
-         pop_size:=0;
 
          { Align stack if required }
-         if not inlined then
-           pop_size:=align_parasize(oldpushedparasize,para_alignment);
+         pop_size:=align_parasize;
 
          { Push parameters }
          oldaktcallnode:=aktcallnode;
@@ -683,31 +669,26 @@ implementation
          { destroy registers containing a parameter for the actual      }
          { function call (e.g. if it's a function, its result will      }
          { overwrite r3, which contains the first parameter) (JM)       }
-         if not(inlined) and
-            assigned(right) then
+         if assigned(right) then
            secondpass(right);
 
-         if inlined or
-            (right = nil) then
-          begin
-             if (po_virtualmethod in procdefinition.procoptions) and
-                 assigned(methodpointer) then
-                begin
-                   secondpass(methodpointer);
-                   location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
-
-                   { virtual methods require an index }
-                   if tprocdef(procdefinition).extnumber=-1 then
-                     internalerror(200304021);
-                   { VMT should already be loaded in a register }
-                   if methodpointer.location.register.number=NR_NO then
-                     internalerror(200304022);
-
-                   { test validity of VMT }
-                   if not(is_interface(tprocdef(procdefinition)._class)) and
-                      not(is_cppclass(tprocdef(procdefinition)._class)) then
-                     cg.g_maybe_testvmt(exprasmlist,methodpointer.location.register,tprocdef(procdefinition)._class);
-                end;
+         if (po_virtualmethod in procdefinition.procoptions) and
+            assigned(methodpointer) then
+           begin
+             secondpass(methodpointer);
+             location_force_reg(exprasmlist,methodpointer.location,OS_ADDR,false);
+
+             { virtual methods require an index }
+             if tprocdef(procdefinition).extnumber=-1 then
+               internalerror(200304021);
+             { VMT should already be loaded in a register }
+             if methodpointer.location.register.number=NR_NO then
+               internalerror(200304022);
+
+             { test validity of VMT }
+             if not(is_interface(tprocdef(procdefinition)._class)) and
+                not(is_cppclass(tprocdef(procdefinition)._class)) then
+               cg.g_maybe_testvmt(exprasmlist,methodpointer.location.register,tprocdef(procdefinition)._class);
            end;
 
          if assigned(left) then
@@ -720,21 +701,9 @@ implementation
                   maybe_save(exprasmlist,left.registers32,methodpointer.location,pushedregs);
 
             {$endif}
-              { be found elsewhere }
-              if inlined then
-                para_offset:=tprocdef(procdefinition).parast.address_fixup+
-                  tprocdef(procdefinition).parast.datasize
-              else
-                para_offset:=0;
-              if not(inlined) and
-                 assigned(right) then
-                tcallparanode(left).secondcallparan(
-                  (po_leftright in procdefinition.procoptions),procdefinition.proccalloption,
-                  para_alignment,para_offset)
-              else
-                tcallparanode(left).secondcallparan(
-                  (po_leftright in procdefinition.procoptions),procdefinition.proccalloption,
-                  para_alignment,para_offset);
+              tcallparanode(left).secondcallparan(
+                (po_leftright in procdefinition.procoptions),procdefinition.proccalloption,
+                 para_alignment,0);
             {$ifndef newra}
               if assigned(right) then
                 maybe_restore(exprasmlist,right.location,pushedregs)
@@ -745,27 +714,14 @@ implementation
            end;
          aktcallnode:=oldaktcallnode;
 
-         { Allocate return value for inlined routines }
-         if inlined and
-            (resulttype.def.size>0) then
-           begin
-             tg.GetTemp(exprasmlist,Align(resulttype.def.size,aktalignment.paraalign),tt_persistent,returnref);
-             inlinecode.retoffset:=returnref.offset;
-           end;
-
          { procedure variable or normal function call ? }
-         if inlined or
-            (right=nil) then
+         if (right=nil) then
            begin
               { push base pointer ?}
-              { never when inlining, since if necessary, the base pointer }
-              { can/will be gottten from the current procedure's symtable }
-              { (JM) }
-              if not inlined then
-                if (current_procdef.parast.symtablelevel>=normal_function_level) and
-                   assigned(tprocdef(procdefinition).parast) and
-                   ((tprocdef(procdefinition).parast.symtablelevel)>normal_function_level) then
-                  push_framepointer;
+              if (current_procdef.parast.symtablelevel>=normal_function_level) and
+                 assigned(tprocdef(procdefinition).parast) and
+                 ((tprocdef(procdefinition).parast.symtablelevel)>normal_function_level) then
+                push_framepointer;
 
               rg.saveintregvars(exprasmlist,regs_to_push_int);
               rg.saveotherregvars(exprasmlist,regs_to_push_other);
@@ -778,28 +734,17 @@ implementation
                       tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber));
                    cg.a_call_ref(exprasmlist,href);
 
-                   { release self }
+                   { release vmt register }
                    rg.ungetaddressregister(exprasmlist,methodpointer.location.register);
                 end
               else
                 begin
-                  if not inlined then
-                   begin
-                     { Calling interrupt from the same code requires some
-                       extra code }
-                     if (po_interrupt in procdefinition.procoptions) then
-                       extra_interrupt_code;
-
-                     cg.a_call_name(exprasmlist,tprocdef(procdefinition).mangledname);
-                   end
-                  else { inlined proc }
-                   begin
-                     { process the inlinecode }
-                     secondpass(tnode(inlinecode));
-                     { free the args }
-                     if tprocdef(procdefinition).parast.datasize>0 then
-                       tg.UnGetTemp(exprasmlist,pararef);
-                   end;
+                  { Calling interrupt from the same code requires some
+                    extra code }
+                  if (po_interrupt in procdefinition.procoptions) then
+                    extra_interrupt_code;
+
+                  cg.a_call_name(exprasmlist,tprocdef(procdefinition).mangledname);
                end;
            end
          else
@@ -818,7 +763,7 @@ implementation
            end;
 
          { Need to remove the parameters from the stack? }
-         if (not inlined) and (po_clearstack in procdefinition.procoptions) then
+         if (po_clearstack in procdefinition.procoptions) then
           begin
             { the old pop_size was already included in pushedparasize }
             pop_size:=pushedparasize;
@@ -832,7 +777,6 @@ implementation
          if pop_size>0 then
            pop_parasize(pop_size);
 
-
 {$ifdef powerpc}
          { this calculation must be done in pass_1 anyway, so don't worry }
          if tppcprocinfo(current_procinfo).maxpushedparasize<pushedparasize then
@@ -848,7 +792,7 @@ implementation
 
          { handle function results }
          if (not is_void(resulttype.def)) then
-           handle_return_value(inlined)
+           handle_return_value
          else
            location_reset(location,LOC_VOID,OS_NO);
 
@@ -864,44 +808,8 @@ implementation
          rg.restoreusedotherregisters(exprasmlist,pushedother);
          rg.restoreusedintregisters(exprasmlist,pushedint);
 
-         { Release temps from parameters }
-         pp:=tcallparanode(left);
-         while assigned(pp) do
-           begin
-              if assigned(pp.left) then
-                begin
-                  { don't release the funcret temp }
-                  if not(vo_is_funcret in tvarsym(pp.paraitem.parasym).varoptions) then
-                    location_freetemp(exprasmlist,pp.left.location);
-                  { process also all nodes of an array of const }
-                  if pp.left.nodetype=arrayconstructorn then
-                    begin
-                      if assigned(tarrayconstructornode(pp.left).left) then
-                       begin
-                         hp:=pp.left;
-                         while assigned(hp) do
-                          begin
-                            location_freetemp(exprasmlist,tarrayconstructornode(hp).left.location);
-                            hp:=tarrayconstructornode(hp).right;
-                          end;
-                       end;
-                    end;
-                end;
-              pp:=tcallparanode(pp.right);
-           end;
-
-         if inlined then
-           begin
-             if (resulttype.def.size>0) then
-               tg.UnGetTemp(exprasmlist,returnref);
-             tprocdef(procdefinition).parast.address_fixup:=store_parast_fixup;
-             right:=inlinecode;
-
-             { from now on the result can be freed normally }
-             if assigned(funcretnode) and
-                paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
-               tg.ChangeTempType(exprasmlist,funcretnode.location.reference,tt_normal);
-           end;
+         { release temps of paras }
+         release_para_temps;
 
          { if return value is not used }
          if (not(nf_return_value_used in flags)) and (not is_void(resulttype.def)) then
@@ -931,186 +839,387 @@ implementation
 
 
 
-{*****************************************************************************
-                             TCGPROCINLINENODE
-*****************************************************************************}
-
-
-    procedure tcgprocinlinenode.pass_2;
-       var st : tsymtable;
-           oldprocdef : tprocdef;
-           ps, i : longint;
-           oldprocinfo : tprocinfo;
-           oldinlining_procedure,
-           nostackframe : boolean;
-           inlineentrycode,inlineexitcode : TAAsmoutput;
-           oldexitlabel,oldexit2label:tasmlabel;
-           oldregstate: pointer;
-           localsref : treference;
+    procedure tcgcallnode.inlined_pass_2;
+      var
+         regs_to_push_int : Tsupregset;
+         regs_to_push_other : tregisterset;
+         unusedstate: pointer;
+         pushedother : tpushedsavedother;
+         pushedint : tpushedsavedint;
+         oldpushedparasize : longint;
+         { adress returned from an I/O-error }
+         iolabel : tasmlabel;
+         { help reference pointer }
+         href : treference;
+         pushedregs : tmaybesave;
+         accreg : tregister;
+         oldaktcallnode : tcallnode;
+         oldprocdef : tprocdef;
+         i : longint;
+         oldprocinfo : tprocinfo;
+         oldinlining_procedure : boolean;
+         inlineentrycode,inlineexitcode : TAAsmoutput;
+         oldexitlabel:tasmlabel;
+         oldregstate: pointer;
+         old_local_fixup,
+         old_para_fixup : longint;
+         pararef,
+         localsref : treference;
 {$ifdef GDB}
-           startlabel,endlabel : tasmlabel;
-           pp : pchar;
-           mangled_length  : longint;
+         startlabel,endlabel : tasmlabel;
+         pp : pchar;
+         mangled_length  : longint;
 {$endif GDB}
-       begin
-          { deallocate the registers used for the current procedure's regvars }
-          if assigned(current_procdef.regvarinfo) then
-            begin
-              with pregvarinfo(current_procdef.regvarinfo)^ do
-                for i := 1 to maxvarregs do
-                  if assigned(regvars[i]) then
-                    store_regvar(exprasmlist,regvars[i].reg);
-              rg.saveStateForInline(oldregstate);
-              { make sure the register allocator knows what the regvars in the }
-              { inlined code block are (JM)                                    }
-              rg.resetusableregisters;
-              rg.clearregistercount;
-            {$ifndef newra}
-              rg.cleartempgen;
-            {$endif}
-              if assigned(inlineprocdef.regvarinfo) then
-                with pregvarinfo(inlineprocdef.regvarinfo)^ do
-                  for i := 1 to maxvarregs do
-                    if assigned(regvars[i]) then
-                      begin
-                        {Fix me!!}
-                        {tmpreg:=rg.makeregsize(regvars[i].reg,OS_INT);
-                        rg.makeregvar(tmpreg);}
-                        internalerror(200301232);
-                      end;
-            end;
-          oldinlining_procedure:=inlining_procedure;
-          oldexitlabel:=aktexitlabel;
-          oldexit2label:=aktexit2label;
-          oldprocdef:=current_procdef;
-          oldprocinfo:=current_procinfo;
-          objectlibrary.getlabel(aktexitlabel);
-          objectlibrary.getlabel(aktexit2label);
-          { we're inlining a procedure }
-          inlining_procedure:=true;
-
-          { create temp procinfo }
-          current_procinfo:=cprocinfo.create(nil);
-          current_procinfo.procdef:=inlineprocdef;
-          current_procinfo.return_offset:=retoffset;
-          current_procdef:=current_procinfo.procdef;
-
-          { arg space has been filled by the parent secondcall }
-          st:=current_procdef.localst;
-          { set it to the same lexical level }
-          st.symtablelevel:=oldprocdef.localst.symtablelevel;
-          if st.datasize>0 then
-            begin
-              tg.GetTemp(exprasmlist,st.datasize,tt_persistent,localsref);
-              if tg.direction>0 then
-                st.address_fixup:=localsref.offset
-              else
-                st.address_fixup:=localsref.offset+st.datasize;
+      begin
+         if not(assigned(procdefinition) and (procdefinition.deftype=procdef)) then
+           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;
+
+         { deallocate the registers used for the current procedure's regvars }
+         if assigned(current_procdef.regvarinfo) then
+           begin
+             with pregvarinfo(current_procdef.regvarinfo)^ do
+               for i := 1 to maxvarregs do
+                 if assigned(regvars[i]) then
+                   store_regvar(exprasmlist,regvars[i].reg);
+             rg.saveStateForInline(oldregstate);
+             { make sure the register allocator knows what the regvars in the }
+             { inlined code block are (JM)                                    }
+             rg.resetusableregisters;
+             rg.clearregistercount;
+           {$ifndef newra}
+             rg.cleartempgen;
+           {$endif}
+             if assigned(tprocdef(procdefinition).regvarinfo) then
+               with pregvarinfo(tprocdef(procdefinition).regvarinfo)^ do
+                 for i := 1 to maxvarregs do
+                   if assigned(regvars[i]) then
+                     begin
+                       {Fix me!!}
+                       {tmpreg:=rg.makeregsize(regvars[i].reg,OS_INT);
+                       rg.makeregvar(tmpreg);}
+                       internalerror(200301232);
+                     end;
+           end;
+
+         { create temp procinfo }
+         current_procinfo:=cprocinfo.create(nil);
+         current_procinfo.procdef:=tprocdef(procdefinition);
+         current_procdef:=current_procinfo.procdef;
+
+         { Localsymtable }
+         current_procdef.localst.symtablelevel:=oldprocdef.localst.symtablelevel;
+         if current_procdef.localst.datasize>0 then
+           begin
+             old_local_fixup:=current_procdef.localst.address_fixup;
+             tg.GetTemp(exprasmlist,current_procdef.localst.datasize,tt_persistent,localsref);
+             if tg.direction>0 then
+               current_procdef.localst.address_fixup:=localsref.offset
+             else
+               current_procdef.localst.address_fixup:=localsref.offset+current_procdef.localst.datasize;
 {$ifdef extdebug}
-              Comment(V_debug,'local symtable is at offset '+tostr(st.address_fixup));
-              exprasmList.concat(tai_comment.Create(strpnew(
-                'local symtable is at offset '+tostr(st.address_fixup))));
+             Comment(V_debug,'inlined local symtable ('+tostr(current_procdef.localst.datasize)+' bytes) is at offset '+tostr(current_procdef.localst.address_fixup));
+             exprasmList.concat(tai_comment.Create(strpnew(
+               'inlined local symtable ('+tostr(current_procdef.localst.datasize)+' bytes) is at offset '+tostr(current_procdef.localst.address_fixup))));
 {$endif extdebug}
-            end;
-          exprasmList.concat(Tai_Marker.Create(InlineStart));
+           end;
+
+         { Parasymtable }
+         current_procdef.parast.symtablelevel:=oldprocdef.localst.symtablelevel;
+         if current_procdef.parast.datasize>0 then
+           begin
+             old_para_fixup:=current_procdef.parast.address_fixup;
+             tg.GetTemp(exprasmlist,current_procdef.parast.datasize,tt_persistent,pararef);
+             current_procdef.parast.address_fixup:=pararef.offset;
 {$ifdef extdebug}
-          exprasmList.concat(tai_comment.Create(strpnew('Start of inlined proc')));
+             Comment(V_debug,'inlined para symtable ('+tostr(current_procdef.parast.datasize)+' bytes) is at offset '+tostr(current_procdef.parast.address_fixup));
+             exprasmList.concat(tai_comment.Create(strpnew(
+               'inlined para symtable ('+tostr(current_procdef.parast.datasize)+' bytes) is at offset '+tostr(current_procdef.parast.address_fixup))));
 {$endif extdebug}
-{$ifdef GDB}
-          if (cs_debuginfo in aktmoduleswitches) then
-            begin
-              objectlibrary.getaddrlabel(startlabel);
-              objectlibrary.getaddrlabel(endlabel);
-              cg.a_label(exprasmlist,startlabel);
-              inlineprocdef.localst.symtabletype:=inlinelocalsymtable;
-              inlineprocdef.parast.symtabletype:=inlineparasymtable;
-
-              { Here we must include the para and local symtable info }
-              inlineprocdef.concatstabto(withdebuglist);
-
-              { set it back for safety }
-              inlineprocdef.localst.symtabletype:=localsymtable;
-              inlineprocdef.parast.symtabletype:=parasymtable;
-
-              mangled_length:=length(oldprocdef.mangledname);
-              getmem(pp,mangled_length+50);
-              strpcopy(pp,'192,0,0,'+startlabel.name);
-              if (target_info.use_function_relative_addresses) then
-                begin
-                  strpcopy(strend(pp),'-');
-                  strpcopy(strend(pp),oldprocdef.mangledname);
-                end;
-              withdebugList.concat(Tai_stabn.Create(strnew(pp)));
-            end;
-{$endif GDB}
-          { takes care of local data initialization }
-          inlineentrycode:=TAAsmoutput.Create;
-          inlineexitcode:=TAAsmoutput.Create;
-          ps:=para_size;
-          genentrycode(inlineentrycode,0,ps,nostackframe,true);
-          if po_assembler in current_procdef.procoptions then
-            inlineentrycode.insert(Tai_marker.Create(asmblockstart));
-          exprasmList.concatlist(inlineentrycode);
-          secondpass(inlinetree);
-          genexitcode(inlineexitcode,0,false,true);
-          if po_assembler in current_procdef.procoptions then
-            inlineexitcode.concat(Tai_marker.Create(asmblockend));
-          exprasmList.concatlist(inlineexitcode);
-
-          inlineentrycode.free;
-          inlineexitcode.free;
+           end;
+
+         { Calculate offsets }
+         current_procinfo.after_header;
+
+         exprasmList.concat(Tai_Marker.Create(InlineStart));
 {$ifdef extdebug}
-          exprasmList.concat(tai_comment.Create(strpnew('End of inlined proc')));
+         exprasmList.concat(tai_comment.Create(strpnew('Start of inlined proc')));
 {$endif extdebug}
-          exprasmList.concat(Tai_Marker.Create(InlineEnd));
-
-          {we can free the local data now, reset also the fixup address }
-          if st.datasize>0 then
-            begin
-              tg.UnGetTemp(exprasmlist,localsref);
-              st.address_fixup:=0;
-            end;
-          { restore procinfo }
-          current_procinfo.free;
-          current_procinfo:=oldprocinfo;
 {$ifdef GDB}
-          if (cs_debuginfo in aktmoduleswitches) then
-            begin
-              cg.a_label(exprasmlist,endlabel);
-              strpcopy(pp,'224,0,0,'+endlabel.name);
+         if (cs_debuginfo in aktmoduleswitches) then
+           begin
+             objectlibrary.getaddrlabel(startlabel);
+             objectlibrary.getaddrlabel(endlabel);
+             cg.a_label(exprasmlist,startlabel);
+             tprocdef(procdefinition).localst.symtabletype:=inlinelocalsymtable;
+             procdefinition.parast.symtabletype:=inlineparasymtable;
+
+             { Here we must include the para and local symtable info }
+             procdefinition.concatstabto(withdebuglist);
+
+             { set it back for safety }
+             tprocdef(procdefinition).localst.symtabletype:=localsymtable;
+             procdefinition.parast.symtabletype:=parasymtable;
+
+             mangled_length:=length(oldprocdef.mangledname);
+             getmem(pp,mangled_length+50);
+             strpcopy(pp,'192,0,0,'+startlabel.name);
              if (target_info.use_function_relative_addresses) then
                begin
                  strpcopy(strend(pp),'-');
                  strpcopy(strend(pp),oldprocdef.mangledname);
                end;
-              withdebugList.concat(Tai_stabn.Create(strnew(pp)));
-              freemem(pp,mangled_length+50);
-            end;
+             withdebugList.concat(Tai_stabn.Create(strnew(pp)));
+           end;
 {$endif GDB}
-          { restore }
-          current_procdef:=oldprocdef;
-          aktexitlabel:=oldexitlabel;
-          aktexit2label:=oldexit2label;
-          inlining_procedure:=oldinlining_procedure;
-
-          { reallocate the registers used for the current procedure's regvars, }
-          { since they may have been used and then deallocated in the inlined  }
-          { procedure (JM)                                                     }
-          if assigned(current_procdef.regvarinfo) then
-            begin
-              rg.restoreStateAfterInline(oldregstate);
-            end;
-       end;
+
+         iolabel:=nil;
+         rg.saveunusedstate(unusedstate);
+
+         { if we allocate the temp. location for ansi- or widestrings }
+         { already here, we avoid later a push/pop                    }
+         if is_widestring(resulttype.def) then
+           begin
+             tg.GetTemp(exprasmlist,pointer_size,tt_widestring,refcountedtemp);
+             cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
+           end
+         else if is_ansistring(resulttype.def) then
+           begin
+             tg.GetTemp(exprasmlist,pointer_size,tt_ansistring,refcountedtemp);
+             cg.g_decrrefcount(exprasmlist,resulttype.def,refcountedtemp,false);
+           end;
+
+         if (cs_check_io in aktlocalswitches) and
+            (po_iocheck in procdefinition.procoptions) and
+            not(po_iocheck in current_procdef.procoptions) then
+           begin
+              objectlibrary.getaddrlabel(iolabel);
+              cg.a_label(exprasmlist,iolabel);
+           end
+         else
+           iolabel:=nil;
+
+         { save all used registers and possible registers
+           used for the return value }
+         regs_to_push_int := tprocdef(procdefinition).usedintregisters;
+         regs_to_push_other := tprocdef(procdefinition).usedotherregisters;
+         if (not is_void(resulttype.def)) and
+            (not paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption)) then
+          begin
+            include(regs_to_push_int,RS_ACCUMULATOR);
+{$ifndef cpu64bit}
+            if resulttype.def.size>sizeof(aword) then
+              include(regs_to_push_int,RS_ACCUMULATORHIGH);
+{$endif cpu64bit}
+          end;
+         rg.saveusedintregisters(exprasmlist,pushedint,regs_to_push_int);
+         rg.saveusedotherregisters(exprasmlist,pushedother,regs_to_push_other);
+
+         { give used registers through }
+         rg.usedintinproc:=rg.usedintinproc + tprocdef(procdefinition).usedintregisters;
+         rg.usedinproc:=rg.usedinproc + tprocdef(procdefinition).usedotherregisters;
+
+         { Initialize for pushing the parameters }
+         oldpushedparasize:=pushedparasize;
+         pushedparasize:=0;
+
+         { Push parameters }
+         oldaktcallnode:=aktcallnode;
+         aktcallnode:=self;
+
+         if assigned(left) then
+           begin
+            {$ifndef newra}
+              if assigned(right) then
+                maybe_save(exprasmlist,left.registers32,right.location,pushedregs)
+              else
+                if assigned(methodpointer) then
+                  maybe_save(exprasmlist,left.registers32,methodpointer.location,pushedregs);
+
+            {$endif}
+              { we push from right to left, so start with parameters at the end of
+                the parameter block }
+              tcallparanode(left).secondcallparan(
+                  (po_leftright in procdefinition.procoptions),procdefinition.proccalloption,
+                  0,procdefinition.parast.address_fixup+procdefinition.parast.datasize);
+            {$ifndef newra}
+              if assigned(right) then
+                maybe_restore(exprasmlist,right.location,pushedregs)
+              else
+                if assigned(methodpointer) then
+                  maybe_restore(exprasmlist,methodpointer.location,pushedregs);
+            {$endif newra}
+           end;
+         aktcallnode:=oldaktcallnode;
+
+         rg.saveintregvars(exprasmlist,regs_to_push_int);
+         rg.saveotherregvars(exprasmlist,regs_to_push_other);
+
+         { takes care of local data initialization }
+         inlineentrycode:=TAAsmoutput.Create;
+         inlineexitcode:=TAAsmoutput.Create;
+
+         geninlineentrycode(inlineentrycode,0);
+         if po_assembler in current_procdef.procoptions then
+           inlineentrycode.insert(Tai_marker.Create(asmblockstart));
+         exprasmList.concatlist(inlineentrycode);
+
+         { process the inline code }
+         secondpass(inlinecode);
+
+{$ifdef powerpc}
+         { this calculation must be done in pass_1 anyway, so don't worry }
+         if tppcprocinfo(current_procinfo).maxpushedparasize<pushedparasize then
+           tppcprocinfo(current_procinfo).maxpushedparasize:=pushedparasize;
+{$endif powerpc}
+
+         { Restore }
+         pushedparasize:=oldpushedparasize;
+         rg.restoreunusedstate(unusedstate);
+{$ifdef TEMPREGDEBUG}
+         testregisters32;
+{$endif TEMPREGDEBUG}
+
+         geninlineexitcode(inlineexitcode,true);
+         if po_assembler in current_procdef.procoptions then
+           inlineexitcode.concat(Tai_marker.Create(asmblockend));
+         exprasmList.concatlist(inlineexitcode);
+
+         inlineentrycode.free;
+         inlineexitcode.free;
+{$ifdef extdebug}
+         exprasmList.concat(tai_comment.Create(strpnew('End of inlined proc')));
+{$endif extdebug}
+         exprasmList.concat(Tai_Marker.Create(InlineEnd));
+
+         {we can free the local data now, reset also the fixup address }
+         if current_procdef.localst.datasize>0 then
+           begin
+             tg.UnGetTemp(exprasmlist,localsref);
+             current_procdef.localst.address_fixup:=old_local_fixup;
+           end;
+         {we can free the para data now, reset also the fixup address }
+         if current_procdef.parast.datasize>0 then
+           begin
+             tg.UnGetTemp(exprasmlist,pararef);
+             current_procdef.parast.address_fixup:=old_para_fixup;
+           end;
+         { free return reference }
+         if (resulttype.def.size>0) then
+           begin
+             { from now on the result can be freed normally }
+//              if assigned(funcretnode) and
+//                 paramanager.ret_in_param(resulttype.def,procdefinition.proccalloption) then
+//                tg.ChangeTempType(exprasmlist,funcretnode.location.reference,tt_normal);
+           end;
+
+         { handle function results }
+         if (not is_void(resulttype.def)) then
+           handle_return_value
+         else
+           location_reset(location,LOC_VOID,OS_NO);
+
+         { perhaps i/o check ? }
+         if iolabel<>nil then
+           begin
+              reference_reset_symbol(href,iolabel,0);
+              cg.a_paramaddr_ref(exprasmlist,href,paramanager.getintparaloc(1));
+              cg.a_call_name(exprasmlist,'FPC_IOCHECK');
+           end;
+
+         { restore registers }
+         rg.restoreusedotherregisters(exprasmlist,pushedother);
+         rg.restoreusedintregisters(exprasmlist,pushedint);
+
+         { release temps of paras }
+         release_para_temps;
+
+         { if return value is not used }
+         if (not is_void(resulttype.def)) and
+            (not(nf_return_value_used in flags)) then
+           begin
+              if location.loc in [LOC_CREFERENCE,LOC_REFERENCE] then
+                begin
+                   { data which must be finalized ? }
+                   if (resulttype.def.needs_inittable) then
+                      cg.g_finalize(exprasmlist,resulttype.def,location.reference,false);
+                   { release unused temp }
+                   tg.ungetiftemp(exprasmlist,location.reference)
+                end
+              else if location.loc=LOC_FPUREGISTER then
+                begin
+{$ifdef x86}
+                  { release FPU stack }
+                  accreg.enum:=FPU_RESULT_REG;
+                  emit_reg(A_FSTP,S_NO,accreg);
+                  {
+                    dec(trgcpu(rg).fpuvaroffset);
+                    do NOT decrement as the increment before
+                    is not called for unused results PM }
+{$endif x86}
+                end;
+           end;
+
+         { release procinfo }
+         current_procinfo.free;
+         current_procinfo:=oldprocinfo;
+
+{$ifdef GDB}
+         if (cs_debuginfo in aktmoduleswitches) then
+           begin
+             cg.a_label(exprasmlist,endlabel);
+             strpcopy(pp,'224,0,0,'+endlabel.name);
+            if (target_info.use_function_relative_addresses) then
+              begin
+                strpcopy(strend(pp),'-');
+                strpcopy(strend(pp),oldprocdef.mangledname);
+              end;
+             withdebugList.concat(Tai_stabn.Create(strnew(pp)));
+             freemem(pp,mangled_length+50);
+           end;
+{$endif GDB}
+
+         { restore }
+         current_procdef:=oldprocdef;
+         aktexitlabel:=oldexitlabel;
+         inlining_procedure:=oldinlining_procedure;
+
+         { reallocate the registers used for the current procedure's regvars, }
+         { since they may have been used and then deallocated in the inlined  }
+         { procedure (JM)                                                     }
+         if assigned(current_procdef.regvarinfo) then
+           rg.restoreStateAfterInline(oldregstate);
+      end;
+
+
+    procedure tcgcallnode.pass_2;
+      begin
+        if assigned(inlinecode) then
+          inlined_pass_2
+        else
+          normal_pass_2;
+      end;
 
 
 begin
    ccallparanode:=tcgcallparanode;
    ccallnode:=tcgcallnode;
-   cprocinlinenode:=tcgprocinlinenode;
 end.
 {
   $Log$
-  Revision 1.74  2003-05-25 11:34:17  peter
+  Revision 1.75  2003-05-26 21:17:17  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.74  2003/05/25 11:34:17  peter
     * methodpointer self pushing fixed
 
   Revision 1.73  2003/05/25 08:59:16  peter

+ 8 - 154
compiler/ncgflw.pas

@@ -695,152 +695,14 @@ implementation
 *****************************************************************************}
 
     procedure tcgexitnode.pass_2;
-
-      var
-         otlabel,oflabel : tasmlabel;
-         cgsize : tcgsize;
-         r,hreg : tregister;
-         allocated_acc,
-         allocated_acchigh: boolean;
-      label
-         do_jmp;
       begin
          location_reset(location,LOC_VOID,OS_NO);
 
          include(flowcontrol,fc_exit);
          if assigned(left) then
-           begin
-             if onlyassign then
-               begin
-                  { just do a normal assignment followed by exit }
-                  secondpass(left);
-                  cg.a_jmp_always(exprasmlist,aktexitlabel);
-               end
-             else
-               begin
-                  allocated_acc := false;
-                  allocated_acchigh := false;
-                  otlabel:=truelabel;
-                  oflabel:=falselabel;
-                  objectlibrary.getlabel(truelabel);
-                  objectlibrary.getlabel(falselabel);
-                  secondpass(left);
-                  { increment reference counter, this is
-                    useless for string constants }
-                  if (left.resulttype.def.needs_inittable) and
-                     (left.nodetype<>stringconstn) then
-                    cg.g_incrrefcount(exprasmlist,left.resulttype.def,left.location.reference,false);
-                  { the result of left is not needed anymore after this
-                    node }
-                  location_freetemp(exprasmlist,left.location);
-                  location_release(exprasmlist,left.location);
-                  case left.location.loc of
-                    LOC_FPUREGISTER :
-                      goto do_jmp;
-{$ifdef cpuflags}
-                    LOC_FLAGS :
-                      begin
-                        r.enum:=R_INTREGISTER;
-                        r.number:=NR_ACCUMULATOR;
-                        cg.a_reg_alloc(exprasmlist,r);
-                        allocated_acc := true;
-                        cg.g_flags2reg(exprasmlist,OS_INT,left.location.resflags,r);
-                        goto do_jmp;
-                      end;
-{$endif cpuflags}
-                    LOC_JUMP :
-                      begin
-                        r.enum:=R_INTREGISTER;
-                        r.number:=(RS_ACCUMULATOR shl 8) or R_SUBL;
-                        cg.a_reg_alloc(exprasmlist,r);
-                        { get an 8-bit register }
-                        allocated_acc := true;
-                        cg.a_label(exprasmlist,truelabel);
-                        cg.a_load_const_reg(exprasmlist,OS_8,1,r);
-                        cg.a_jmp_always(exprasmlist,aktexit2label);
-                        cg.a_label(exprasmlist,falselabel);
-                        cg.a_load_const_reg(exprasmlist,OS_8,0,r);
-                        goto do_jmp;
-                      end;
-                  end;
-                  case current_procdef.rettype.def.deftype of
-                    pointerdef,
-                    procvardef :
-                      begin
-                        r.enum:=R_INTREGISTER;
-                        r.number:=NR_ACCUMULATOR;
-                        cg.a_reg_alloc(exprasmlist,r);
-                        allocated_acc := true;
-                        cg.a_load_loc_reg(exprasmlist,left.location,r);
-                      end;
-                    floatdef :
-                      begin
-{$ifdef cpufpemu}
-                        if cs_fp_emulation in aktmoduleswitches then
-                           r.enum := accumulator
-                        else
-{$endif cpufpemu}
-                           r.enum:=fpu_result_reg;
-{$ifndef i386}
-                        cg.a_reg_alloc(exprasmlist,r);
-{$endif not i386}
-                        cg.a_loadfpu_loc_reg(exprasmlist,left.location,r);
-                      end;
-                    else
-                      begin
-                        cgsize:=def_cgsize(current_procdef.rettype.def);
-                        allocated_acc := true;
-{$ifndef cpu64bit}
-
-                        if cgsize in [OS_64,OS_S64] then
-                          begin
-                             r.enum:=R_INTREGISTER;
-                             r.number:=NR_ACCUMULATOR;
-                             hreg.enum:=R_INTREGISTER;
-                             hreg.number:=NR_ACCUMULATORHIGH;
-                             cg.a_reg_alloc(exprasmlist,r);
-                             cg.a_reg_alloc(exprasmlist,hreg);
-                             allocated_acchigh := true;
-                             cg64.a_load64_loc_reg(exprasmlist,left.location,
-                                 joinreg64(r,hreg));
-                           end
-                         else
-{$endif cpu64bit}
-                           begin
-                             r.enum:=R_INTREGISTER;
-                             r.number:=(RS_ACCUMULATOR shl 8) or cgsize2subreg(cgsize);
-                             cg.a_reg_alloc(exprasmlist,r);
-                             cg.a_load_loc_reg(exprasmlist,left.location,r);
-                           end;
-                     end;
-                  end;
+           secondpass(left);
 
-               do_jmp:
-                  truelabel:=otlabel;
-                  falselabel:=oflabel;
-                  cg.a_jmp_always(exprasmlist,aktexit2label);
-                  r.enum:=R_INTREGISTER;
-                  r.number:=NR_ACCUMULATOR;
-{$ifndef cpu64bit}
-                  hreg.enum:=R_INTREGISTER;
-                  hreg.number:=NR_ACCUMULATORHIGH;
-{$endif cpu64bit}
-
-                  if allocated_acc then
-                    cg.a_reg_dealloc(exprasmlist,r);
-{$ifndef cpu64bit}
-                  if allocated_acchigh then
-                    cg.a_reg_dealloc(exprasmlist,hreg);
-{$endif cpu64bit}
-{$ifndef i386}
-                  r.enum:=fpu_result_reg;
-                  if (current_procdef.rettype.def.deftype = floatdef) then
-                    cg.a_reg_dealloc(exprasmlist,r);
-{$endif not i386}
-               end;
-           end
-         else
-           cg.a_jmp_always(exprasmlist,aktexitlabel);
+         cg.a_jmp_always(exprasmlist,aktexitlabel);
        end;
 
 
@@ -1033,7 +895,6 @@ implementation
          doobjectdestroy,
          doobjectdestroyandreraise,
          oldaktexitlabel,
-         oldaktexit2label,
          oldaktcontinuelabel,
          oldaktbreaklabel : tasmlabel;
          oldflowcontrol,tryflowcontrol,
@@ -1054,7 +915,6 @@ implementation
 
          { save the old labels for control flow statements }
          oldaktexitlabel:=aktexitlabel;
-         oldaktexit2label:=aktexit2label;
          if assigned(aktbreaklabel) then
            begin
               oldaktcontinuelabel:=aktcontinuelabel;
@@ -1082,7 +942,6 @@ implementation
          { try block }
          { set control flow labels for the try block }
          aktexitlabel:=exittrylabel;
-         aktexit2label:=exittrylabel;
          if assigned(oldaktbreaklabel) then
           begin
             aktcontinuelabel:=continuetrylabel;
@@ -1104,7 +963,6 @@ implementation
          { set control flow labels for the except block }
          { and the on statements                        }
          aktexitlabel:=exitexceptlabel;
-         aktexit2label:=exitexceptlabel;
          if assigned(oldaktbreaklabel) then
           begin
             aktcontinuelabel:=continueexceptlabel;
@@ -1228,7 +1086,6 @@ implementation
 
          { restore the control flow labels }
          aktexitlabel:=oldaktexitlabel;
-         aktexit2label:=oldaktexit2label;
          if assigned(oldaktbreaklabel) then
           begin
             aktcontinuelabel:=oldaktcontinuelabel;
@@ -1248,7 +1105,6 @@ implementation
          continueonlabel,
          breakonlabel,
          oldaktexitlabel,
-         oldaktexit2label,
          oldaktcontinuelabel,
          doobjectdestroyandreraise,
          doobjectdestroy,
@@ -1295,10 +1151,8 @@ implementation
          if assigned(right) then
            begin
               oldaktexitlabel:=aktexitlabel;
-              oldaktexit2label:=aktexit2label;
               objectlibrary.getlabel(exitonlabel);
               aktexitlabel:=exitonlabel;
-              aktexit2label:=exitonlabel;
               if assigned(aktbreaklabel) then
                begin
                  oldaktcontinuelabel:=aktcontinuelabel;
@@ -1354,7 +1208,6 @@ implementation
                 end;
 
               aktexitlabel:=oldaktexitlabel;
-              aktexit2label:=oldaktexit2label;
               if assigned(oldaktbreaklabel) then
                begin
                  aktcontinuelabel:=oldaktcontinuelabel;
@@ -1387,7 +1240,6 @@ implementation
          continuefinallylabel,
          breakfinallylabel,
          oldaktexitlabel,
-         oldaktexit2label,
          oldaktcontinuelabel,
          oldaktbreaklabel : tasmlabel;
          oldflowcontrol,tryflowcontrol : tflowcontrol;
@@ -1409,13 +1261,11 @@ implementation
          { the finally block must catch break, continue and exit }
          { statements                                            }
          oldaktexitlabel:=aktexitlabel;
-         oldaktexit2label:=aktexit2label;
          if implicitframe then
            exitfinallylabel:=finallylabel
          else
            objectlibrary.getlabel(exitfinallylabel);
          aktexitlabel:=exitfinallylabel;
-         aktexit2label:=exitfinallylabel;
          if assigned(aktbreaklabel) then
           begin
             oldaktcontinuelabel:=aktcontinuelabel;
@@ -1528,7 +1378,6 @@ implementation
          cg.a_label(exprasmlist,endfinallylabel);
 
          aktexitlabel:=oldaktexitlabel;
-         aktexit2label:=oldaktexit2label;
          if assigned(aktbreaklabel) then
           begin
             aktcontinuelabel:=oldaktcontinuelabel;
@@ -1554,7 +1403,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.63  2003-05-23 14:27:35  peter
+  Revision 1.64  2003-05-26 21:17:17  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.63  2003/05/23 14:27:35  peter
     * remove some unit dependencies
     * current_procinfo changes to store more info
 

+ 203 - 148
compiler/ncgutil.pas

@@ -62,12 +62,11 @@ interface
                               para_offset:longint;alignment : longint;
                               const locpara : tparalocation);
 
-    procedure genentrycode(list : TAAsmoutput;
-                           stackframe:longint;
-                           var parasize:longint;
-                           var nostackframe:boolean;
-                           inlined : boolean);
-   procedure genexitcode(list : TAAsmoutput;parasize:longint;nostackframe:boolean;inlined:boolean);
+    procedure genentrycode(list : TAAsmoutput;stackframe:longint;inlined : boolean);
+    procedure genexitcode(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.
@@ -1185,8 +1184,57 @@ implementation
       end;
 
 
+    procedure initretvalue(list:taasmoutput);
+      var
+        paraloc : tparalocation;
+        href    : treference;
+      begin
+        if not is_void(current_procdef.rettype.def) then
+          begin
+             { for now the pointer to the result can't be a register }
+             if paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
+               begin
+{$ifdef powerpc}
+                  { no stack space is allocated in this case -> can't save the result reg on the stack }
+                  if not(po_assembler in current_procdef.procoptions) then
+{$endif powerpc}
+                    begin
+                      paraloc:=paramanager.getfuncretparaloc(current_procdef);
+                      reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset);
+                      case paraloc.loc of
+                        LOC_CREGISTER,
+                        LOC_REGISTER:
+                          if not(paraloc.size in [OS_64,OS_S64]) then
+                            cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href)
+                          else
+                            cg64.a_load64_reg_ref(list,paraloc.register64,href);
+                        LOC_CFPUREGISTER,
+                        LOC_FPUREGISTER:
+                          cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href);
+                        LOC_CMMREGISTER,
+                        LOC_MMREGISTER:
+                          cg.a_loadmm_reg_ref(list,paraloc.register,href);
+                      end;
+                    end;
+               end;
 
-    procedure handle_return_value(list:TAAsmoutput; inlined : boolean;var uses_acc,uses_acchi,uses_fpu : boolean);
+             { initialize return value }
+             if (current_procdef.rettype.def.needs_inittable) then
+               begin
+{$ifdef powerpc}
+                  if (po_assembler in current_procdef.procoptions) then
+                    internalerror(200304161);
+{$endif powerpc}
+                  if (cs_implicit_exceptions in aktmoduleswitches) then
+                    include(current_procinfo.flags,pi_needs_implicit_finally);
+                  reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset);
+                  cg.g_initialize(list,current_procdef.rettype.def,href,paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption));
+               end;
+          end;
+      end;
+
+
+    procedure handle_return_value(list:TAAsmoutput; var uses_acc,uses_acchi,uses_fpu : boolean);
       var
         href : treference;
         hreg,r,r2 : tregister;
@@ -1267,65 +1315,12 @@ implementation
       end;
 
 
-    procedure handle_fast_exit_return_value(list:TAAsmoutput);
-      var
-        href : treference;
-        hreg : tregister;
-        cgsize : TCGSize;
-        r,r2 : Tregister;
-      begin
-        if not is_void(current_procdef.rettype.def) then
-         begin
-           reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset);
-           cgsize:=def_cgsize(current_procdef.rettype.def);
-           case current_procdef.rettype.def.deftype of
-             orddef,
-             enumdef :
-               begin
-{$ifndef cpu64bit}
-                 r.enum:=accumulator;
-                 r2.enum:=accumulatorhigh;
-                 if cgsize in [OS_64,OS_S64] then
-                   cg64.a_load64_reg_ref(list,joinreg64(r,r2),href)
-                 else
-{$endif cpu64bit}
-                  begin
-                    hreg:=rg.makeregsize(r,cgsize);
-                    cg.a_load_reg_ref(list,cgsize,hreg,href);
-                  end;
-               end;
-             floatdef :
-               begin
-{$ifdef cpufpemu}
-                  if cs_fp_emulation in aktmoduleswitches then
-                    r.enum := accumulator
-                 else
-{$endif cpufpemu}
-                    r.enum:=fpu_result_reg;
-                 cg.a_loadfpu_reg_ref(list,cgsize,r,href);
-               end;
-             else
-               begin
-                 r.enum:=accumulator;
-                 if not paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
-                  cg.a_load_reg_ref(list,cgsize,r,href);
-               end;
-           end;
-         end;
-      end;
-
-
-    procedure genentrycode(list : TAAsmoutput;
-                           stackframe:longint;
-                           var parasize:longint;
-                           var nostackframe:boolean;
-                           inlined : boolean);
+    procedure genentrycode(list : TAAsmoutput;stackframe:longint;inlined : boolean);
       var
         hs : string;
         href : treference;
         stackalloclist : taasmoutput;
         hp : tparaitem;
-        paraloc : tparalocation;
         rsp : tregister;
       begin
         if not inlined then
@@ -1424,48 +1419,8 @@ implementation
               cg.g_profilecode(list);
           end;
 
-        if not is_void(current_procdef.rettype.def) then
-          begin
-             { for now the pointer to the result can't be a register }
-             if paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
-               begin
-{$ifdef powerpc}
-                  { no stack space is allocated in this case -> can't save the result reg on the stack }
-                  if not(po_assembler in current_procdef.procoptions) then
-{$endif powerpc}
-                    begin
-                      paraloc:=paramanager.getfuncretparaloc(current_procdef);
-                      reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset);
-                      case paraloc.loc of
-                        LOC_CREGISTER,
-                        LOC_REGISTER:
-                          if not(paraloc.size in [OS_64,OS_S64]) then
-                            cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href)
-                          else
-                            cg64.a_load64_reg_ref(list,paraloc.register64,href);
-                        LOC_CFPUREGISTER,
-                        LOC_FPUREGISTER:
-                          cg.a_load_reg_ref(list,paraloc.size,paraloc.register,href);
-                        LOC_CMMREGISTER,
-                        LOC_MMREGISTER:
-                          cg.a_loadmm_reg_ref(list,paraloc.register,href);
-                      end;
-                    end;
-               end;
-
-             { initialize return value }
-             if (current_procdef.rettype.def.needs_inittable) then
-               begin
-{$ifdef powerpc}
-                  if (po_assembler in current_procdef.procoptions) then
-                    internalerror(200304161);
-{$endif powerpc}
-                  if (cs_implicit_exceptions in aktmoduleswitches) then
-                    include(current_procinfo.flags,pi_needs_implicit_finally);
-                  reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset);
-                  cg.g_initialize(list,current_procdef.rettype.def,href,paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption));
-               end;
-          end;
+        { initialize return value }
+        initretvalue(list);
 
         { initialize local data like ansistrings }
         case current_procdef.proctypeoption of
@@ -1508,9 +1463,9 @@ implementation
                  (cs_profile in aktmoduleswitches) then
                begin
                  reference_reset_symbol(href,objectlibrary.newasmsymboldata('etext'),0);
-                 cg.a_paramaddr_ref(list,href,paraloc);
+                 cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(2));
                  reference_reset_symbol(href,objectlibrary.newasmsymboldata('__image_base__'),0);
-                 cg.a_paramaddr_ref(list,href,paraloc);
+                 cg.a_paramaddr_ref(list,href,paramanager.getintparaloc(2));
                  cg.a_call_name(list,'_monstartup');
                end;
 
@@ -1577,23 +1532,12 @@ implementation
            if (current_procinfo.framepointer.number=NR_STACK_POINTER_REG) then
             begin
               CGMessage(cg_d_stackframe_omited);
-              nostackframe:=true;
-              if (current_procdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
-                parasize:=0
-              else
-                parasize:=current_procdef.parast.datasize+current_procdef.parast.address_fixup-4;
               if stackframe<>0 then
                 cg.g_stackpointer_alloc(stackalloclist,stackframe);
             end
            else
 {$endif powerpc}
             begin
-              nostackframe:=false;
-              if (current_procdef.proctypeoption in [potype_unitinit,potype_proginit,potype_unitfinalize]) then
-                parasize:=0
-              else
-                parasize:=current_procdef.parast.datasize+current_procdef.parast.address_fixup-target_info.first_parm_offset;
-
               if (po_interrupt in current_procdef.procoptions) then
                 cg.g_interrupt_stackframe_entry(stackalloclist);
 
@@ -1612,7 +1556,7 @@ implementation
       end;
 
 
-   procedure genexitcode(list : TAAsmoutput;parasize:longint;nostackframe:boolean;inlined:boolean);
+   procedure genexitcode(list : TAAsmoutput;inlined:boolean);
       var
 {$ifdef GDB}
         stabsendlabel : tasmlabel;
@@ -1627,15 +1571,6 @@ implementation
         usesfpu : boolean;
         rsp,r  : Tregister;
       begin
-        if aktexit2label.is_used and
-           ((pi_needs_implicit_finally in current_procinfo.flags) or
-            (pi_uses_exceptions in current_procinfo.flags)) then
-          begin
-            cg.a_jmp_always(list,aktexitlabel);
-            cg.a_label(list,aktexit2label);
-            handle_fast_exit_return_value(list);
-          end;
-
         if aktexitlabel.is_used then
           cg.a_label(list,aktexitlabel);
 
@@ -1701,12 +1636,9 @@ implementation
                 usesacc:=true;
               end
             else
-              handle_return_value(list,inlined,usesacc,usesacchi,usesfpu)
+              handle_return_value(list,usesacc,usesacchi,usesfpu)
           end;
 
-        if aktexit2label.is_used and not aktexit2label.is_set then
-          cg.a_label(list,aktexit2label);
-
 {$ifdef GDB}
         if ((cs_debuginfo in aktmoduleswitches) and not inlined) then
           begin
@@ -1739,14 +1671,13 @@ implementation
         { remove stackframe }
         if not inlined then
          begin
-           if (not nostackframe) then
-            cg.g_restore_frame_pointer(list)
+           if (current_procinfo.framepointer.number=NR_STACK_POINTER_REG) then
+            begin
+              if (tg.gettempsize<>0) then
+                cg.a_op_const_reg(list,OP_ADD,tg.gettempsize,current_procinfo.framepointer);
+            end
            else
-            if (tg.gettempsize<>0) then
-              begin
-                 r.enum:=stack_pointer_reg;
-                 cg.a_op_const_reg(list,OP_ADD,tg.gettempsize,r);
-              end;
+            cg.g_restore_frame_pointer(list);
          end;
 
         { at last, the return is generated }
@@ -1755,16 +1686,7 @@ implementation
            if (po_interrupt in current_procdef.procoptions) then
             cg.g_interrupt_stackframe_exit(list,usesacc,usesacchi)
            else
-             begin
-{$ifndef i386}
-               { give a warning if the limit of parameters allowed for
-                 certain processors is reached.
-               }
-               if (parasize > maxparasize) then
-                 Message(cg_w_parasize_too_big);
-{$endif}
-               cg.g_return_from_proc(list,parasize);
-             end;
+            cg.g_return_from_proc(list,current_procdef.parast.datasize);
          end;
 
         if not inlined then
@@ -1833,10 +1755,143 @@ implementation
          cleanup_regvars(list);
       end;
 
+
+{****************************************************************************
+                                 Inlining
+****************************************************************************}
+
+    procedure handle_inlined_return_value(list:TAAsmoutput);
+      var
+        href : treference;
+        r,r2 : tregister;
+        cgsize : TCGSize;
+      begin
+        if not is_void(current_procdef.rettype.def) then
+         begin
+           reference_reset_base(href,current_procinfo.framepointer,current_procinfo.return_offset);
+           cgsize:=def_cgsize(current_procdef.rettype.def);
+           { Here, we return the function result. In most architectures, the value is
+             passed into the accumulator, 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
+{$ifndef cpu64bit}
+                 if cgsize in [OS_64,OS_S64] then
+                  begin
+                    r:=rg.getregisterint(list,OS_INT);
+                    r2:=rg.getregisterint(list,OS_INT);
+                    cg64.a_load64_ref_reg(list,href,joinreg64(r,r2));
+                  end
+                 else
+{$endif cpu64bit}
+                  begin
+                    r:=rg.getregisterint(list,cgsize);
+                    cg.a_load_ref_reg(list,cgsize,href,r);
+                  end;
+               end;
+             floatdef :
+               begin
+{$ifdef cpufpemu}
+                  if cs_fp_emulation in aktmoduleswitches then
+                    r.enum := accumulator
+                 else
+{$endif cpufpemu}
+                  r.enum:=fpu_result_reg;
+                 cg.a_loadfpu_ref_reg(list,cgsize,href,r);
+               end;
+             else
+               begin
+                 if not paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) then
+                  begin
+{$ifndef cpu64bit}
+                    { Win32 can return records in EAX:EDX }
+                    if cgsize in [OS_64,OS_S64] then
+                     begin
+                       r:=rg.getregisterint(list,OS_INT);
+                       r2:=rg.getregisterint(list,OS_INT);
+                       cg64.a_load64_ref_reg(list,href,joinreg64(r,r2));
+                     end
+                    else
+{$endif cpu64bit}
+                     begin
+                       r:=rg.getregisterint(list,cgsize);
+                       cg.a_load_ref_reg(list,cgsize,href,r);
+                     end;
+                   end
+               end;
+           end;
+         end;
+      end;
+
+
+    procedure geninlineentrycode(list : TAAsmoutput;stackframe:longint);
+      begin
+        { initialize return value }
+        initretvalue(list);
+
+        current_procdef.localst.foreach_static({$ifndef TP}@{$endif}initialize_data,list);
+
+        { initialisizes temp. ansi/wide string data }
+        inittempvariables(list);
+
+        { initialize ansi/widesstring para's }
+        if assigned(current_procdef.parast) then
+          current_procdef.parast.foreach_static({$ifndef TP}@{$endif}init_paras,list);
+
+        { 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);
+
+        load_regvars(list,nil);
+      end;
+
+
+   procedure geninlineexitcode(list : TAAsmoutput;inlined:boolean);
+      var
+        usesacc,
+        usesacchi,
+        usesfpu : boolean;
+      begin
+        if aktexitlabel.is_used then
+          cg.a_label(list,aktexitlabel);
+
+        cleanup_regvars(list);
+
+        { finalize temporary data }
+        finalizetempvariables(list);
+
+        current_procdef.localst.foreach_static({$ifndef TP}@{$endif}finalize_data,list);
+
+        { finalize paras data }
+        if assigned(current_procdef.parast) then
+          current_procdef.parast.foreach_static({$ifndef TP}@{$endif}final_paras,list);
+
+        { handle return value, this is not done for assembler routines when
+          they didn't reference the result variable }
+        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
+             internalerror(200305263);
+//            handle_inlined_return_value(list);
+             handle_return_value(list,usesacc,usesacchi,usesfpu)
+          end;
+
+        cleanup_regvars(list);
+      end;
+
 end.
 {
   $Log$
-  Revision 1.106  2003-05-24 11:59:42  jonas
+  Revision 1.107  2003-05-26 21:17:17  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.106  2003/05/24 11:59:42  jonas
     * fixed integer typeconversion problems
 
   Revision 1.105  2003/05/23 14:27:35  peter

+ 15 - 33
compiler/nflw.pas

@@ -93,7 +93,6 @@ interface
        tfornodeclass = class of tfornode;
 
        texitnode = class(tunarynode)
-          onlyassign : boolean;
           constructor create(l:tnode);virtual;
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
@@ -835,56 +834,34 @@ implementation
     constructor texitnode.create(l:tnode);
       begin
         inherited create(exitn,l);
-        onlyassign:=false;
       end;
 
 
     constructor texitnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
       begin
         inherited ppuload(t,ppufile);
-        onlyassign:=boolean(ppufile.getbyte);
       end;
 
 
     procedure texitnode.ppuwrite(ppufile:tcompilerppufile);
       begin
         inherited ppuwrite(ppufile);
-        ppufile.putbyte(byte(onlyassign));
       end;
 
 
     function texitnode.det_resulttype:tnode;
       begin
         result:=nil;
-        { Check the 2 types }
-        if not inlining_procedure then
-         begin
-           if assigned(left) then
-            begin
-              inserttypeconv(left,current_procdef.rettype);
-              if paramanager.ret_in_param(current_procdef.rettype.def,current_procdef.proccalloption) or
-                 (current_procdef.proctypeoption=potype_constructor) or
-                 (pi_needs_implicit_finally in current_procinfo.flags) or
-                 (pi_uses_exceptions in current_procinfo.flags) then
-               begin
-                 left:=cassignmentnode.create(
-                     cloadnode.create(current_procdef.funcretsym,current_procdef.funcretsym.owner),
-                     left);
-                 onlyassign:=true;
-               end
-              else
-               begin
-                 { mark funcretsym as assigned }
-                 inc(tvarsym(current_procdef.funcretsym).refs);
-                 tvarsym(current_procdef.funcretsym).varstate:=vs_assigned;
-               end;
-            end;
-         end;
         if assigned(left) then
-         begin
-           resulttypepass(left);
-           set_varstate(left,true);
-         end;
+          begin
+            { add assignment to funcretsym }
+            inserttypeconv(left,current_procdef.rettype);
+            left:=cassignmentnode.create(
+                cloadnode.create(current_procdef.funcretsym,current_procdef.funcretsym.owner),
+                left);
+            resulttypepass(left);
+            set_varstate(left,true);
+          end;
         resulttype:=voidtype;
       end;
 
@@ -1449,7 +1426,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.74  2003-05-13 19:14:41  peter
+  Revision 1.75  2003-05-26 21:17:17  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.74  2003/05/13 19:14:41  peter
     * failn removed
     * inherited result code check moven to pexpr
 

+ 6 - 3
compiler/node.pas

@@ -109,7 +109,6 @@ interface
           asn,              {Represents the as typecast}
           caretn,           {Represents the ^ operator}
           starstarn,        {Represents the ** operator exponentiation }
-          procinlinen,      {Procedures that can be inlined }
           arrayconstructorn, {Construction node for [...] parsing}
           arrayconstructorrangen, {Range element to allow sets in array construction tree}
           tempcreaten,      { for temps in the result/firstpass }
@@ -188,7 +187,6 @@ interface
           'asn',
           'caretn',
           'starstarn',
-          'procinlinen',
           'arrayconstructn',
           'arrayconstructrangen',
           'tempcreaten',
@@ -984,7 +982,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.61  2003-05-13 19:14:41  peter
+  Revision 1.62  2003-05-26 21:17:17  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.61  2003/05/13 19:14:41  peter
     * failn removed
     * inherited result code check moven to pexpr
 

+ 15 - 7
compiler/nutils.pas

@@ -84,9 +84,11 @@ implementation
       end;
       case n.nodetype of
         calln:
-          result := foreachnode(tcallnode(n).methodpointer,f) or result;
-        procinlinen:
-          result := foreachnode(tprocinlinenode(n).inlinetree,f) or result;
+          begin
+            { not in one statement, won't work because of b- }
+            result := foreachnode(tcallnode(n).methodpointer,f) or result;
+            result := foreachnode(tcallnode(n).inlinecode,f) or result;
+          end;
         ifn, whilerepeatn, forn:
           begin
             { not in one statement, won't work because of b- }
@@ -129,9 +131,10 @@ implementation
       end;
       case n.nodetype of
         calln:
-          result := foreachnodestatic(tcallnode(n).methodpointer,f) or result;
-        procinlinen:
-          result := foreachnodestatic(tprocinlinenode(n).inlinetree,f) or result;
+          begin
+            result := foreachnodestatic(tcallnode(n).methodpointer,f) or result;
+            result := foreachnodestatic(tcallnode(n).inlinecode,f) or result;
+          end;
         ifn, whilerepeatn, forn:
           begin
             { not in one statement, won't work because of b- }
@@ -250,7 +253,12 @@ end.
 
 {
   $Log$
-  Revision 1.4  2003-05-16 14:33:31  peter
+  Revision 1.5  2003-05-26 21:17:17  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.4  2003/05/16 14:33:31  peter
     * regvar fixes
 
   Revision 1.3  2003/05/13 20:54:06  peter

+ 6 - 2
compiler/pass_2.pas

@@ -134,7 +134,6 @@ implementation
              'as',    {asn}
              'error-caret',       {caretn}
              'add-starstar',  {starstarn}
-             'procinline',  {procinlinen}
              'arrayconstruc', {arrayconstructn}
              'noth-arrcnstr',     {arrayconstructrangen}
              'tempcreaten',
@@ -301,7 +300,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.52  2003-05-15 18:58:53  peter
+  Revision 1.53  2003-05-26 21:17:17  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.52  2003/05/15 18:58:53  peter
     * removed selfpointer_offset, vmtpointer_offset
     * tvarsym.adjusted_address
     * address in localsymtable is now in the real direction

+ 9 - 12
compiler/pmodules.pas

@@ -768,11 +768,8 @@ implementation
 
     procedure gen_implicit_initfinal(list:taasmoutput;flag:word;st:tsymtable);
       var
-        parasize : longint;
-        nostackframe : boolean;
         pd : tprocdef;
-        oldexitlabel,
-        oldexit2label : tasmlabel;
+        oldexitlabel : tasmlabel;
       begin
         { update module flags }
         current_module.flags:=current_module.flags or flag;
@@ -793,20 +790,15 @@ implementation
         end;
         { save labels }
         oldexitlabel:=aktexitlabel;
-        oldexit2label:=aktexit2label;
         { generate a dummy function }
-        parasize:=0;
-        nostackframe:=false;
         objectlibrary.getlabel(aktexitlabel);
-        objectlibrary.getlabel(aktexit2label);
         include(current_procinfo.flags,pi_do_call);
-        genentrycode(list,0,parasize,nostackframe,false);
-        genexitcode(list,parasize,nostackframe,false);
+        genentrycode(list,0,false);
+        genexitcode(list,false);
         list.convert_registers;
         release_main_proc(pd);
         { restore }
         aktexitlabel:=oldexitlabel;
-        aktexit2label:=oldexit2label;
       end;
 
 
@@ -1482,7 +1474,12 @@ So, all parameters are passerd into registers in sparc architecture.}
 end.
 {
   $Log$
-  Revision 1.108  2003-05-25 10:27:12  peter
+  Revision 1.109  2003-05-26 21:17:17  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.108  2003/05/25 10:27:12  peter
     * moved Comment calls to messge file
 
   Revision 1.107  2003/05/22 21:31:35  peter

+ 9 - 12
compiler/psub.pas

@@ -551,14 +551,9 @@ implementation
       var
         oldprocdef : tprocdef;
         oldprocinfo : tprocinfo;
-        oldexitlabel,
-        oldexit2label : tasmlabel;
+        oldexitlabel : tasmlabel;
         oldaktmaxfpuregisters : longint;
         oldfilepos : tfileposinfo;
-        { true when no stackframe is required }
-        nostackframe:boolean;
-        { number of bytes which have to be cleared by RET }
-        parasize:longint;
       begin
         { the initialization procedure can be empty, then we
           don't need to generate anything. When it was an empty
@@ -576,10 +571,8 @@ implementation
 
         { save old labels }
         oldexitlabel:=aktexitlabel;
-        oldexit2label:=aktexit2label;
         { get new labels }
         objectlibrary.getlabel(aktexitlabel);
-        objectlibrary.getlabel(aktexit2label);
         aktbreaklabel:=nil;
         aktcontinuelabel:=nil;
 
@@ -599,12 +592,12 @@ implementation
         { first generate entry code with the correct position and switches }
         aktfilepos:=current_procinfo.entrypos;
         aktlocalswitches:=current_procinfo.entryswitches;
-        genentrycode(current_procinfo.aktentrycode,0,parasize,nostackframe,false);
+        genentrycode(current_procinfo.aktentrycode,0,false);
 
         { now generate exit code with the correct position and switches }
         aktfilepos:=current_procinfo.exitpos;
         aktlocalswitches:=current_procinfo.exitswitches;
-        genexitcode(current_procinfo.aktexitcode,parasize,nostackframe,false);
+        genexitcode(current_procinfo.aktexitcode,false);
 
         { now all the registers used are known }
         current_procdef.usedintregisters:=rg.usedintinproc;
@@ -666,7 +659,6 @@ implementation
 
         { restore labels }
         aktexitlabel:=oldexitlabel;
-        aktexit2label:=oldexit2label;
 
         { restore }
         aktmaxfpuregisters:=oldaktmaxfpuregisters;
@@ -1216,7 +1208,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.117  2003-05-25 08:59:47  peter
+  Revision 1.118  2003-05-26 21:17:18  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.117  2003/05/25 08:59:47  peter
     * do not generate code when there was an error
 
   Revision 1.116  2003/05/23 18:49:55  jonas

+ 6 - 2
compiler/psystem.pas

@@ -423,7 +423,6 @@ implementation
         nodeclass[asn]:=casnode;
         nodeclass[caretn]:=caddnode;
         nodeclass[starstarn]:=caddnode;
-        nodeclass[procinlinen]:=cprocinlinenode;
         nodeclass[arrayconstructorn]:=carrayconstructornode;
         nodeclass[arrayconstructorrangen]:=carrayconstructorrangenode;
         nodeclass[tempcreaten]:=ctempcreatenode;
@@ -494,7 +493,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.51  2003-05-25 11:34:17  peter
+  Revision 1.52  2003-05-26 21:17:18  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.51  2003/05/25 11:34:17  peter
     * methodpointer self pushing fixed
 
   Revision 1.50  2003/05/13 19:14:41  peter

+ 6 - 25
compiler/symdef.pas

@@ -429,7 +429,6 @@ interface
           function  concatpara(afterpara:tparaitem;const tt:ttype;sym : tsym;defval:tsym;vhidden:boolean):tparaitem;
           function  insertpara(const tt:ttype;sym : tsym;defval:tsym;vhidden:boolean):tparaitem;
           procedure removepara(currpara:tparaitem);
-          function  para_size(alignsize:longint) : longint;
           function  typename_paras(showhidden:boolean): string;
           procedure test_if_fpu_result;
           function  is_methodpointer:boolean;virtual;
@@ -3278,29 +3277,6 @@ implementation
 
 
 
-    function tabstractprocdef.para_size(alignsize:longint) : longint;
-      var
-         pdc : TParaItem;
-         l : longint;
-      begin
-         l:=0;
-         pdc:=TParaItem(Para.first);
-         while assigned(pdc) do
-          begin
-            inc(l,paramanager.push_size(pdc.paratyp,pdc.paratype.def,proccalloption));
-            l:=align(l,alignsize);
-            if assigned(pdc.paratype.def) and
-               is_special_array(pdc.paratype.def) then
-              begin
-                inc(l,POINTER_SIZE);
-                l:=align(l,alignsize);
-              end;
-            pdc:=TParaItem(pdc.next);
-          end;
-         para_size:=l;
-      end;
-
-
     function tabstractprocdef.typename_paras(showhidden:boolean) : string;
       var
         hs,s : string;
@@ -5762,7 +5738,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.145  2003-05-25 11:34:17  peter
+  Revision 1.146  2003-05-26 21:17:18  peter
+    * procinlinenode removed
+    * aktexit2label removed, fast exit removed
+    + tcallnode.inlined_pass_2 added
+
+  Revision 1.145  2003/05/25 11:34:17  peter
     * methodpointer self pushing fixed
 
   Revision 1.144  2003/05/15 18:58:53  peter