Quellcode durchsuchen

* procvar handling for tp procvar mode fixed
* proc to procvar moved from addrnode to typeconvnode
* inlininginfo is now allocated only for inline routines that
can be inlined, introduced a new flag po_has_inlining_info

peter vor 20 Jahren
Ursprung
Commit
2b6456fe16

+ 18 - 13
compiler/defcmp.pas

@@ -41,7 +41,7 @@ interface
        tcompare_defs_option = (cdo_internal,cdo_explicit,cdo_check_operator,cdo_allow_variant);
        tcompare_defs_option = (cdo_internal,cdo_explicit,cdo_check_operator,cdo_allow_variant);
        tcompare_defs_options = set of tcompare_defs_option;
        tcompare_defs_options = set of tcompare_defs_option;
 
 
-       tconverttype = (
+       tconverttype = (tc_none,
           tc_equal,
           tc_equal,
           tc_not_possible,
           tc_not_possible,
           tc_string_2_string,
           tc_string_2_string,
@@ -165,6 +165,9 @@ implementation
          hd3 : tobjectdef;
          hd3 : tobjectdef;
          hpd : tprocdef;
          hpd : tprocdef;
       begin
       begin
+         eq:=te_incompatible;
+         doconv:=tc_not_possible;
+
          { safety check }
          { safety check }
          if not(assigned(def_from) and assigned(def_to)) then
          if not(assigned(def_from) and assigned(def_to)) then
           begin
           begin
@@ -175,14 +178,13 @@ implementation
          { same def? then we've an exact match }
          { same def? then we've an exact match }
          if def_from=def_to then
          if def_from=def_to then
           begin
           begin
+            doconv:=tc_equal;
             compare_defs_ext:=te_exact;
             compare_defs_ext:=te_exact;
             exit;
             exit;
           end;
           end;
 
 
          { we walk the wanted (def_to) types and check then the def_from
          { we walk the wanted (def_to) types and check then the def_from
            types if there is a conversion possible }
            types if there is a conversion possible }
-         eq:=te_incompatible;
-         doconv:=tc_not_possible;
          case def_to.deftype of
          case def_to.deftype of
            orddef :
            orddef :
              begin
              begin
@@ -786,13 +788,10 @@ implementation
                    end;
                    end;
                  procvardef :
                  procvardef :
                    begin
                    begin
-                     { procedure variable can be assigned to an void pointer }
-                     { Not anymore. Use the @ operator now.}
-                     if not(m_tp_procvar in aktmodeswitches) and
-                       { method pointers can't be assigned to void pointers
-                       not(tprocvardef(def_from).is_methodpointer) and }
-                        (tpointerdef(def_to).pointertype.def.deftype=orddef) and
-                        (torddef(tpointerdef(def_to).pointertype.def).typ=uvoid) then
+                     { procedure variable can be assigned to an void pointer,
+                       this not allowed for methodpointers }
+                     if is_void(tpointerdef(def_to).pointertype.def) and
+                        tprocvardef(def_from).is_addressonly then
                       begin
                       begin
                         doconv:=tc_equal;
                         doconv:=tc_equal;
                         eq:=te_convert_l1;
                         eq:=te_convert_l1;
@@ -879,8 +878,8 @@ implementation
                       { for example delphi allows the assignement from pointers }
                       { for example delphi allows the assignement from pointers }
                       { to procedure variables                                  }
                       { to procedure variables                                  }
                       if (m_pointer_2_procedure in aktmodeswitches) and
                       if (m_pointer_2_procedure in aktmodeswitches) and
-                         (tpointerdef(def_from).pointertype.def.deftype=orddef) and
-                         (torddef(tpointerdef(def_from).pointertype.def).typ=uvoid) then
+                         is_void(tpointerdef(def_from).pointertype.def) and
+                         tprocvardef(def_to).is_addressonly then
                        begin
                        begin
                          doconv:=tc_equal;
                          doconv:=tc_equal;
                          eq:=te_convert_l1;
                          eq:=te_convert_l1;
@@ -1312,7 +1311,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.61  2004-11-29 17:32:56  peter
+  Revision 1.62  2004-12-05 12:28:10  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.61  2004/11/29 17:32:56  peter
     * prevent some IEs with delphi methodpointers
     * prevent some IEs with delphi methodpointers
 
 
   Revision 1.60  2004/11/26 22:33:54  peter
   Revision 1.60  2004/11/26 22:33:54  peter

+ 84 - 40
compiler/htypechk.pas

@@ -128,8 +128,8 @@ interface
     procedure make_not_regable(p : tnode);
     procedure make_not_regable(p : tnode);
     procedure calcregisters(p : tbinarynode;r32,fpu,mmx : word);
     procedure calcregisters(p : tbinarynode;r32,fpu,mmx : word);
 
 
-    { subroutine handling }
-    function  is_procsym_load(p:tnode):boolean;
+    { procvar handling }
+    function  is_procvar_load(p:tnode):boolean;
     procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
     procedure test_local_to_procvar(from_def:tprocvardef;to_def:tdef);
 
 
     { sets varsym varstate field correctly }
     { sets varsym varstate field correctly }
@@ -143,6 +143,7 @@ interface
     function  valid_for_formal_const(p : tnode) : boolean;
     function  valid_for_formal_const(p : tnode) : boolean;
     function  valid_for_var(p:tnode):boolean;
     function  valid_for_var(p:tnode):boolean;
     function  valid_for_assignment(p:tnode):boolean;
     function  valid_for_assignment(p:tnode):boolean;
+    function  valid_for_addr(p : tnode) : boolean;
 
 
 
 
 implementation
 implementation
@@ -152,12 +153,12 @@ implementation
        cutils,verbose,globals,
        cutils,verbose,globals,
        symtable,
        symtable,
        defutil,defcmp,
        defutil,defcmp,
-       nbas,ncnv,nld,nmem,ncal,nmat,nutils,
+       nbas,ncnv,nld,nmem,ncal,nmat,ninl,nutils,
        cgbase,procinfo
        cgbase,procinfo
        ;
        ;
 
 
     type
     type
-      TValidAssign=(Valid_Property,Valid_Void,Valid_Const);
+      TValidAssign=(Valid_Property,Valid_Void,Valid_Const,Valid_Addr);
       TValidAssigns=set of TValidAssign;
       TValidAssigns=set of TValidAssign;
 
 
 
 
@@ -703,22 +704,16 @@ implementation
                           Subroutine Handling
                           Subroutine Handling
 ****************************************************************************}
 ****************************************************************************}
 
 
-    function is_procsym_load(p:tnode):boolean;
+    function is_procvar_load(p:tnode):boolean;
       begin
       begin
-         { ignore vecn,subscriptn }
-         repeat
-           case p.nodetype of
-             vecn :
-               p:=tvecnode(p).left;
-             subscriptn :
-               p:=tsubscriptnode(p).left;
-             else
-               break;
-           end;
-         until false;
-         is_procsym_load:=((p.nodetype=loadn) and (tloadnode(p).symtableentry.typ=procsym)) or
-                          ((p.nodetype=addrn) and (taddrnode(p).left.nodetype=loadn)
-                          and (tloadnode(taddrnode(p).left).symtableentry.typ=procsym)) ;
+        result:=false;
+        { remove voidpointer typecast for tp procvars }
+        if (m_tp_procvar in aktmodeswitches) and
+           (p.nodetype=typeconvn) and
+           is_voidpointer(p.resulttype.def) then
+          p:=tunarynode(p).left;
+        result:=(p.nodetype=typeconvn) and
+                (ttypeconvnode(p).convtype=tc_proc_2_procvar);
       end;
       end;
 
 
 
 
@@ -832,8 +827,13 @@ implementation
         gotderef : boolean;
         gotderef : boolean;
         fromdef,
         fromdef,
         todef    : tdef;
         todef    : tdef;
+        errmsg   : longint;
       begin
       begin
-        valid_for_assign:=false;
+        if valid_const in opts then
+          errmsg:=type_e_variable_id_expected
+        else
+          errmsg:=type_e_argument_cant_be_assigned;
+        result:=false;
         gotsubscript:=false;
         gotsubscript:=false;
         gotvec:=false;
         gotvec:=false;
         gotderef:=false;
         gotderef:=false;
@@ -844,7 +844,7 @@ implementation
         if not(valid_void in opts) and
         if not(valid_void in opts) and
            is_void(hp.resulttype.def) then
            is_void(hp.resulttype.def) then
          begin
          begin
-           CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
+           CGMessagePos(hp.fileinfo,errmsg);
            exit;
            exit;
          end;
          end;
         while assigned(hp) do
         while assigned(hp) do
@@ -853,7 +853,7 @@ implementation
            if (nf_isproperty in hp.flags) then
            if (nf_isproperty in hp.flags) then
             begin
             begin
               if (valid_property in opts) then
               if (valid_property in opts) then
-               valid_for_assign:=true
+               result:=true
               else
               else
                begin
                begin
                  { check return type }
                  { check return type }
@@ -867,18 +867,26 @@ implementation
                      gotclass:=true;
                      gotclass:=true;
                  end;
                  end;
                  { 1. if it returns a pointer and we've found a deref,
                  { 1. if it returns a pointer and we've found a deref,
-                   2. if it returns a class or record and a subscription or with is found }
+                   2. if it returns a class or record and a subscription or with is found
+                   3. if the address is needed of a field (subscriptn) }
                  if (gotpointer and gotderef) or
                  if (gotpointer and gotderef) or
-                    (gotclass and (gotsubscript or gotwith)) then
-                   valid_for_assign:=true
+                    (
+                     gotclass and
+                     (gotsubscript or gotwith)
+                    ) or
+                    (
+                     (Valid_Addr in opts) and
+                     (hp.nodetype=subscriptn)
+                    ) then
+                   result:=true
                  else
                  else
-                   CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
+                   CGMessagePos(hp.fileinfo,errmsg);
                end;
                end;
               exit;
               exit;
             end;
             end;
            if (Valid_Const in opts) and is_constnode(hp) then
            if (Valid_Const in opts) and is_constnode(hp) then
              begin
              begin
-               valid_for_assign:=true;
+               result:=true;
                exit;
                exit;
              end;
              end;
            case hp.nodetype of
            case hp.nodetype of
@@ -924,7 +932,7 @@ implementation
                  if not(gotsubscript or gotvec or gotderef) and
                  if not(gotsubscript or gotvec or gotderef) and
                     not(ttypeconvnode(hp).assign_allowed) then
                     not(ttypeconvnode(hp).assign_allowed) then
                    begin
                    begin
-                     CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
+                     CGMessagePos(hp.fileinfo,errmsg);
                      exit;
                      exit;
                    end;
                    end;
                  case hp.resulttype.def.deftype of
                  case hp.resulttype.def.deftype of
@@ -955,7 +963,7 @@ implementation
                    of reference. }
                    of reference. }
                  if not(gotsubscript or gotderef or gotvec) then
                  if not(gotsubscript or gotderef or gotvec) then
                    begin
                    begin
-                     CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
+                     CGMessagePos(hp.fileinfo,errmsg);
                      exit;
                      exit;
                    end;
                    end;
                  hp:=tunarynode(hp).left;
                  hp:=tunarynode(hp).left;
@@ -981,16 +989,15 @@ implementation
                  if ((hp.resulttype.def.deftype=pointerdef) or
                  if ((hp.resulttype.def.deftype=pointerdef) or
                      (is_integer(hp.resulttype.def) and gotpointer)) and
                      (is_integer(hp.resulttype.def) and gotpointer)) and
                     gotderef then
                     gotderef then
-                  valid_for_assign:=true
+                  result:=true
                  else
                  else
                   CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
                   CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
                  exit;
                  exit;
                end;
                end;
              addrn :
              addrn :
                begin
                begin
-                 if gotderef or
-                    (nf_procvarload in hp.flags) then
-                  valid_for_assign:=true
+                 if gotderef then
+                  result:=true
                  else
                  else
                   CGMessagePos(hp.fileinfo,type_e_no_assign_to_addr);
                   CGMessagePos(hp.fileinfo,type_e_no_assign_to_addr);
                  exit;
                  exit;
@@ -1022,9 +1029,18 @@ implementation
                    2. if it returns a class or record and a subscription or with is found }
                    2. if it returns a class or record and a subscription or with is found }
                  if (gotpointer and gotderef) or
                  if (gotpointer and gotderef) or
                     (gotclass and (gotsubscript or gotwith)) then
                     (gotclass and (gotsubscript or gotwith)) then
-                  valid_for_assign:=true
+                  result:=true
                  else
                  else
-                  CGMessagePos(hp.fileinfo,type_e_argument_cant_be_assigned);
+                  CGMessagePos(hp.fileinfo,errmsg);
+                 exit;
+               end;
+             inlinen :
+               begin
+                 if (valid_const in opts) and
+                    (tinlinenode(hp).inlinenumber in [in_typeof_x]) then
+                   result:=true
+                 else
+                   CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
                  exit;
                  exit;
                end;
                end;
              loadn :
              loadn :
@@ -1044,7 +1060,7 @@ implementation
                         begin
                         begin
                           { allow p^:= constructions with p is const parameter }
                           { allow p^:= constructions with p is const parameter }
                           if gotderef or (Valid_Const in opts) then
                           if gotderef or (Valid_Const in opts) then
-                           valid_for_assign:=true
+                           result:=true
                           else
                           else
                            CGMessagePos(tloadnode(hp).fileinfo,type_e_no_assign_to_const);
                            CGMessagePos(tloadnode(hp).fileinfo,type_e_no_assign_to_const);
                           exit;
                           exit;
@@ -1059,18 +1075,34 @@ implementation
                         end
                         end
                        else
                        else
                         begin
                         begin
-                          valid_for_assign:=true;
+                          result:=true;
                           exit;
                           exit;
                         end;
                         end;
                      end;
                      end;
                    typedconstsym :
                    typedconstsym :
                      begin
                      begin
                        if ttypedconstsym(tloadnode(hp).symtableentry).is_writable then
                        if ttypedconstsym(tloadnode(hp).symtableentry).is_writable then
-                        valid_for_assign:=true
+                        result:=true
                        else
                        else
                         CGMessagePos(hp.fileinfo,type_e_no_assign_to_const);
                         CGMessagePos(hp.fileinfo,type_e_no_assign_to_const);
                        exit;
                        exit;
                      end;
                      end;
+                   procsym :
+                     begin
+                       if (Valid_Const in opts) then
+                         result:=true
+                       else
+                         CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+                       exit;
+                     end;
+                   labelsym :
+                     begin
+                       if (Valid_Addr in opts) then
+                         result:=true
+                       else
+                         CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
+                       exit;
+                     end;
                    else
                    else
                      begin
                      begin
                        CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
                        CGMessagePos(hp.fileinfo,type_e_variable_id_expected);
@@ -1102,7 +1134,7 @@ implementation
 
 
     function  valid_for_formal_const(p : tnode) : boolean;
     function  valid_for_formal_const(p : tnode) : boolean;
       begin
       begin
-        valid_for_formal_const:=is_procsym_load(p) or (p.resulttype.def.deftype=formaldef) or
+        valid_for_formal_const:=(p.resulttype.def.deftype=formaldef) or
           valid_for_assign(p,[valid_void,valid_const,valid_property]);
           valid_for_assign(p,[valid_void,valid_const,valid_property]);
       end;
       end;
 
 
@@ -1113,6 +1145,12 @@ implementation
       end;
       end;
 
 
 
 
+    function  valid_for_addr(p : tnode) : boolean;
+      begin
+        result:=valid_for_assign(p,[valid_const,valid_addr,valid_void]);
+      end;
+
+
     procedure var_para_allowed(var eq:tequaltype;def_from,def_to:Tdef);
     procedure var_para_allowed(var eq:tequaltype;def_from,def_to:Tdef);
       begin
       begin
         { Note: eq must be already valid, it will only be updated! }
         { Note: eq must be already valid, it will only be updated! }
@@ -1933,7 +1971,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.105  2004-11-29 21:40:54  peter
+  Revision 1.106  2004-12-05 12:28:10  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.105  2004/11/29 21:40:54  peter
     * fixed wrong calculation for checking default parameters
     * fixed wrong calculation for checking default parameters
 
 
   Revision 1.104  2004/11/15 23:35:31  peter
   Revision 1.104  2004/11/15 23:35:31  peter

+ 12 - 9
compiler/ncal.pas

@@ -24,8 +24,6 @@ unit ncal;
 
 
 {$i fpcdefs.inc}
 {$i fpcdefs.inc}
 
 
-{ define NODEINLINE}
-
 interface
 interface
 
 
     uses
     uses
@@ -2053,7 +2051,7 @@ type
                     tempnode := ctempcreatenode.create(voidpointertype,voidpointertype.def.size,tt_persistent,tparavarsym(para.parasym).varregable<>vr_none);
                     tempnode := ctempcreatenode.create(voidpointertype,voidpointertype.def.size,tt_persistent,tparavarsym(para.parasym).varregable<>vr_none);
                     addstatement(createstatement,tempnode);
                     addstatement(createstatement,tempnode);
                     addstatement(createstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
                     addstatement(createstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
-                      caddrnode.create(para.left)));
+                      caddrnode.create_internal(para.left)));
                     para.left := ctypeconvnode.create_internal(cderefnode.create(ctemprefnode.create(tempnode)),para.left.resulttype);
                     para.left := ctypeconvnode.create_internal(cderefnode.create(ctemprefnode.create(tempnode)),para.left.resulttype);
                     addstatement(deletestatement,ctempdeletenode.create(tempnode));
                     addstatement(deletestatement,ctempdeletenode.create(tempnode));
                   end;
                   end;
@@ -2081,7 +2079,8 @@ type
         body : tnode;
         body : tnode;
         i: longint;
         i: longint;
       begin
       begin
-        if not assigned(tprocdef(procdefinition).inlininginfo^.code) then
+        if not(assigned(tprocdef(procdefinition).inlininginfo) and
+               assigned(tprocdef(procdefinition).inlininginfo^.code)) then
           internalerror(200412021);
           internalerror(200412021);
         { inherit flags }
         { inherit flags }
         current_procinfo.flags := current_procinfo.flags + ((procdefinition as tprocdef).inlininginfo^.flags*inherited_inlining_flags);
         current_procinfo.flags := current_procinfo.flags + ((procdefinition as tprocdef).inlininginfo^.flags*inherited_inlining_flags);
@@ -2121,15 +2120,13 @@ type
       begin
       begin
          result:=nil;
          result:=nil;
 
 
-{$ifdef NODEINLINE}
+         { Can we inline the procedure? }
          if (procdefinition.proccalloption=pocall_inline) and
          if (procdefinition.proccalloption=pocall_inline) and
-            { can we inline this procedure at the node level? }
-            (tprocdef(procdefinition).inlininginfo^.inlinenode) then
+            (po_has_inlininginfo in procdefinition.procoptions) then
            begin
            begin
              result:=pass1_inline;
              result:=pass1_inline;
              exit;
              exit;
            end;
            end;
-{$endif NODEINLINE}
 
 
          { calculate the parameter info for the procdef }
          { calculate the parameter info for the procdef }
          if not procdefinition.has_paraloc_info then
          if not procdefinition.has_paraloc_info then
@@ -2435,7 +2432,13 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.267  2004-12-03 16:07:04  peter
+  Revision 1.268  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.267  2004/12/03 16:07:04  peter
     * fix crashes with nodeinlining
     * fix crashes with nodeinlining
 
 
   Revision 1.266  2004/12/02 19:26:14  peter
   Revision 1.266  2004/12/02 19:26:14  peter

+ 8 - 11
compiler/ncgcal.pas

@@ -402,16 +402,7 @@ implementation
                   if (parasym.varspez=vs_const) and
                   if (parasym.varspez=vs_const) and
                      (left.location.loc=LOC_CONSTANT) then
                      (left.location.loc=LOC_CONSTANT) then
                     location_force_mem(exprasmlist,left.location);
                     location_force_mem(exprasmlist,left.location);
-
-                  { allow (typecasted) @var }
-                  hp:=left;
-                  while (hp.nodetype=typeconvn) do
-                    hp:=ttypeconvnode(hp).left;
-                  if (hp.nodetype=addrn) and
-                     (not(nf_procvarload in hp.flags)) then
-                    cg.a_param_loc(exprasmlist,left.location,tempcgpara)
-                  else
-                    push_addr_para;
+                  push_addr_para;
                end
                end
              { Normal parameter }
              { Normal parameter }
              else
              else
@@ -1262,7 +1253,13 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.189  2004-12-02 19:26:15  peter
+  Revision 1.190  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.189  2004/12/02 19:26:15  peter
     * disable pass2inline
     * disable pass2inline
 
 
   Revision 1.188  2004/11/21 18:13:31  peter
   Revision 1.188  2004/11/21 18:13:31  peter

+ 12 - 11
compiler/ncgcnv.pas

@@ -319,20 +319,15 @@ interface
 
 
 
 
     procedure tcgtypeconvnode.second_proc_to_procvar;
     procedure tcgtypeconvnode.second_proc_to_procvar;
-
       begin
       begin
-        { method pointer ? }
-        if tabstractprocdef(left.resulttype.def).is_methodpointer and
-           not(tabstractprocdef(left.resulttype.def).is_addressonly) then
+        if tabstractprocdef(resulttype.def).is_addressonly then
           begin
           begin
-             location_copy(location,left.location);
+            location_reset(location,LOC_REGISTER,OS_ADDR);
+            location.register:=cg.getaddressregister(exprasmlist);
+            cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
           end
           end
         else
         else
-          begin
-             location_reset(location,LOC_REGISTER,OS_ADDR);
-             location.register:=cg.getaddressregister(exprasmlist);
-             cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
-          end;
+          location_copy(location,left.location);
       end;
       end;
 
 
 
 
@@ -534,7 +529,13 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.65  2004-11-29 21:02:08  peter
+  Revision 1.66  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.65  2004/11/29 21:02:08  peter
     * location_force_reg in second_nothing can reuse LOC_CREGISTER
     * location_force_reg in second_nothing can reuse LOC_CREGISTER
 
 
   Revision 1.64  2004/11/29 17:32:56  peter
   Revision 1.64  2004/11/29 17:32:56  peter

+ 8 - 19
compiler/ncgmem.pas

@@ -207,26 +207,9 @@ implementation
       begin
       begin
          secondpass(left);
          secondpass(left);
 
 
-         { when loading procvar we do nothing with this node, so load the
-           location of left }
-         if nf_procvarload in flags then
-          begin
-            location_copy(location,left.location);
-            exit;
-          end;
-
          location_reset(location,LOC_REGISTER,OS_ADDR);
          location_reset(location,LOC_REGISTER,OS_ADDR);
          location.register:=cg.getaddressregister(exprasmlist);
          location.register:=cg.getaddressregister(exprasmlist);
-         { @ on a procvar means returning an address to the procedure that
-           is stored in it }
-         if (m_tp_procvar in aktmodeswitches) and
-            (left.nodetype=loadn) and
-            (tloadnode(left).resulttype.def.deftype=procvardef) and
-            assigned(tloadnode(left).symtableentry) and
-            (tloadnode(left).symtableentry.typ in [globalvarsym,localvarsym,paravarsym]) then
-           cg.a_load_ref_reg(exprasmlist,OS_ADDR,OS_ADDR,left.location.reference,location.register)
-         else
-           cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
+         cg.a_loadaddr_ref_reg(exprasmlist,left.location.reference,location.register);
       end;
       end;
 
 
 
 
@@ -878,7 +861,13 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.102  2004-11-08 22:09:59  peter
+  Revision 1.103  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.102  2004/11/08 22:09:59  peter
     * tvarsym splitted
     * tvarsym splitted
 
 
   Revision 1.101  2004/11/01 23:30:11  peter
   Revision 1.101  2004/11/01 23:30:11  peter

+ 9 - 3
compiler/ncgset.pas

@@ -91,7 +91,7 @@ implementation
       paramgr,
       paramgr,
       pass_2,tgobj,
       pass_2,tgobj,
       nbas,ncon,nflw,
       nbas,ncon,nflw,
-      ncgutil,regvars,cpuinfo,
+      ncgutil,regvars,
       cgutils;
       cgutils;
 
 
 
 
@@ -806,7 +806,7 @@ implementation
                      end
                      end
                    else
                    else
                      begin
                      begin
-                        max_dist:=4*aword(labels);
+                        max_dist:=4*labelcnt;
                         if jumptable_no_range then
                         if jumptable_no_range then
                           max_linear_list:=4
                           max_linear_list:=4
                         else
                         else
@@ -870,7 +870,13 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.71  2004-11-30 18:13:39  jonas
+  Revision 1.72  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.71  2004/11/30 18:13:39  jonas
     * patch from Peter to fix inlining of case statements
     * patch from Peter to fix inlining of case statements
 
 
   Revision 1.70  2004/10/31 21:45:03  peter
   Revision 1.70  2004/10/31 21:45:03  peter

+ 13 - 3
compiler/ncgutil.pas

@@ -105,8 +105,10 @@ interface
 
 
     procedure gen_alloc_symtable(list:TAAsmoutput;st:tsymtable);
     procedure gen_alloc_symtable(list:TAAsmoutput;st:tsymtable);
     procedure gen_free_symtable(list:TAAsmoutput;st:tsymtable);
     procedure gen_free_symtable(list:TAAsmoutput;st:tsymtable);
+{$ifdef PASS2INLINE}
     procedure gen_alloc_inline_parast(list:TAAsmoutput;pd:tprocdef);
     procedure gen_alloc_inline_parast(list:TAAsmoutput;pd:tprocdef);
     procedure gen_alloc_inline_funcret(list:TAAsmoutput;pd:tprocdef);
     procedure gen_alloc_inline_funcret(list:TAAsmoutput;pd:tprocdef);
+{$endif PASS2INLINE}
 
 
     { rtti and init/final }
     { rtti and init/final }
     procedure generate_rtti(p:Ttypesym);
     procedure generate_rtti(p:Ttypesym);
@@ -2075,6 +2077,7 @@ implementation
       end;
       end;
 
 
 
 
+{$ifdef PASS2INLINE}
     procedure gen_alloc_inline_parast(list:TAAsmoutput;pd:tprocdef);
     procedure gen_alloc_inline_parast(list:TAAsmoutput;pd:tprocdef);
       var
       var
         sym : tsym;
         sym : tsym;
@@ -2166,12 +2169,12 @@ implementation
                 end;
                 end;
               LOC_REGISTER:
               LOC_REGISTER:
                 begin
                 begin
-{$ifndef cpu64bit}
+  {$ifndef cpu64bit}
                   if callerparaloc.size in [OS_64,OS_S64] then
                   if callerparaloc.size in [OS_64,OS_S64] then
                     begin
                     begin
                     end
                     end
                   else
                   else
-{$endif cpu64bit}
+  {$endif cpu64bit}
                     begin
                     begin
                       pd.funcretloc[calleeside].register:=cg.getintregister(list,pd.funcretloc[calleeside].size);
                       pd.funcretloc[calleeside].register:=cg.getintregister(list,pd.funcretloc[calleeside].size);
                       pd.funcretloc[callerside].register:=pd.funcretloc[calleeside].register;
                       pd.funcretloc[callerside].register:=pd.funcretloc[calleeside].register;
@@ -2204,6 +2207,7 @@ implementation
               end;
               end;
           end;
           end;
       end;
       end;
+{$endif PASS2INLINE}
 
 
 
 
     { persistent rtti generation }
     { persistent rtti generation }
@@ -2282,7 +2286,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.246  2004-12-03 16:06:31  peter
+  Revision 1.247  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.246  2004/12/03 16:06:31  peter
     * fix for int64 parameters passed in a single LOC_REFERENCE of 8 bytes
     * fix for int64 parameters passed in a single LOC_REFERENCE of 8 bytes
 
 
   Revision 1.245  2004/11/21 18:13:31  peter
   Revision 1.245  2004/11/21 18:13:31  peter

+ 331 - 313
compiler/ncnv.pas

@@ -40,6 +40,7 @@ interface
           constructor create(node : tnode;const t : ttype);virtual;
           constructor create(node : tnode;const t : ttype);virtual;
           constructor create_explicit(node : tnode;const t : ttype);
           constructor create_explicit(node : tnode;const t : ttype);
           constructor create_internal(node : tnode;const t : ttype);
           constructor create_internal(node : tnode;const t : ttype);
+          constructor create_proc_to_procvar(node : tnode);
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure buildderefimpl;override;
           procedure buildderefimpl;override;
@@ -75,6 +76,7 @@ interface
           function resulttype_call_helper(c : tconverttype) : tnode;
           function resulttype_call_helper(c : tconverttype) : tnode;
           function resulttype_variant_to_enum : tnode;
           function resulttype_variant_to_enum : tnode;
           function resulttype_enum_to_variant : tnode;
           function resulttype_enum_to_variant : tnode;
+          function resulttype_proc_to_procvar : tnode;
        protected
        protected
           function first_int_to_int : tnode;virtual;
           function first_int_to_int : tnode;virtual;
           function first_cstring_to_pchar : tnode;virtual;
           function first_cstring_to_pchar : tnode;virtual;
@@ -198,9 +200,9 @@ interface
 implementation
 implementation
 
 
    uses
    uses
-      globtype,systems,
+      cclasses,globtype,systems,
       cutils,verbose,globals,widestr,
       cutils,verbose,globals,widestr,
-      symconst,symdef,symsym,symtable,
+      symconst,symdef,symsym,symbase,symtable,
       ncon,ncal,nset,nadd,ninl,nmem,nmat,nutils,
       ncon,ncal,nset,nadd,ninl,nmem,nmat,nutils,
       cgbase,procinfo,
       cgbase,procinfo,
       htypechk,pass_1,cpuinfo;
       htypechk,pass_1,cpuinfo;
@@ -500,7 +502,7 @@ implementation
 
 
       begin
       begin
          inherited create(typeconvn,node);
          inherited create(typeconvn,node);
-         convtype:=tc_not_possible;
+         convtype:=tc_none;
          totype:=t;
          totype:=t;
          if t.def=nil then
          if t.def=nil then
           internalerror(200103281);
           internalerror(200103281);
@@ -526,6 +528,14 @@ implementation
       end;
       end;
 
 
 
 
+    constructor ttypeconvnode.create_proc_to_procvar(node : tnode);
+
+      begin
+         self.create(node,voidtype);
+         convtype:=tc_proc_2_procvar;
+      end;
+
+
     constructor ttypeconvnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
     constructor ttypeconvnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
       begin
       begin
         inherited ppuload(t,ppufile);
         inherited ppuload(t,ppufile);
@@ -948,6 +958,7 @@ implementation
          { evaluate again, reset resulttype so the convert_typ
          { evaluate again, reset resulttype so the convert_typ
            will be calculated again and cstring_to_pchar will
            will be calculated again and cstring_to_pchar will
            be used for futher conversion }
            be used for futher conversion }
+         convtype:=tc_none;
          result:=det_resulttype;
          result:=det_resulttype;
       end;
       end;
 
 
@@ -1027,7 +1038,7 @@ implementation
       begin
       begin
         result := ccallnode.createinternres(
         result := ccallnode.createinternres(
           'fpc_variant_to_dynarray',
           'fpc_variant_to_dynarray',
-          ccallparanode.create(caddrnode.create(crttinode.create(tstoreddef(resulttype.def),initrtti)),
+          ccallparanode.create(caddrnode.create_internal(crttinode.create(tstoreddef(resulttype.def),initrtti)),
             ccallparanode.create(left,nil)
             ccallparanode.create(left,nil)
           ),resulttype);
           ),resulttype);
         resulttypepass(result);
         resulttypepass(result);
@@ -1040,7 +1051,7 @@ implementation
       begin
       begin
         result := ccallnode.createinternres(
         result := ccallnode.createinternres(
           'fpc_dynarray_to_variant',
           'fpc_dynarray_to_variant',
-          ccallparanode.create(caddrnode.create(crttinode.create(tstoreddef(resulttype.def),initrtti)),
+          ccallparanode.create(caddrnode.create_internal(crttinode.create(tstoreddef(resulttype.def),initrtti)),
             ccallparanode.create(ctypeconvnode.create_explicit(left,voidpointertype),nil)
             ccallparanode.create(ctypeconvnode.create_explicit(left,voidpointertype),nil)
           ),resulttype);
           ),resulttype);
         resulttypepass(result);
         resulttypepass(result);
@@ -1070,10 +1081,61 @@ implementation
       end;
       end;
 
 
 
 
+    procedure copyparasym(p:TNamedIndexItem;arg:pointer);
+      var
+        newparast : tsymtable absolute arg;
+        vs : tparavarsym;
+      begin
+        if tsym(p).typ<>paravarsym then
+          exit;
+        with tparavarsym(p) do
+          begin
+            vs:=tparavarsym.create(realname,paranr,varspez,vartype);
+            vs.varoptions:=varoptions;
+            vs.defaultconstsym:=defaultconstsym;
+            newparast.insert(vs);
+          end;
+      end;
+
+
+    function ttypeconvnode.resulttype_proc_to_procvar : tnode;
+      var
+        pd : tabstractprocdef;
+      begin
+        result:=nil;
+        pd:=tabstractprocdef(left.resulttype.def);
+
+        { create procvardef }
+        resulttype.setdef(tprocvardef.create(pd.parast.symtablelevel));
+        tprocvardef(resulttype.def).proctypeoption:=pd.proctypeoption;
+        tprocvardef(resulttype.def).proccalloption:=pd.proccalloption;
+        tprocvardef(resulttype.def).procoptions:=pd.procoptions;
+        tprocvardef(resulttype.def).rettype:=pd.rettype;
+
+        { method ? then set the methodpointer flag }
+        if (pd.owner.symtabletype=objectsymtable) then
+          include(tprocvardef(resulttype.def).procoptions,po_methodpointer);
+
+        { only need the address of the method? this is needed
+          for @tobject.create. In this case there will be a loadn without
+          a methodpointer. }
+        if (left.nodetype=loadn) and
+           not assigned(tloadnode(left).left) then
+          include(tprocvardef(resulttype.def).procoptions,po_addressonly);
+
+        { Add parameters use only references, we don't need to keep the
+          parast. We use the parast from the original function to calculate
+          our parameter data and reset it afterwards }
+        pd.parast.foreach_static(@copyparasym,tprocvardef(resulttype.def).parast);
+        tprocvardef(resulttype.def).calcparas;
+      end;
+
+
     function ttypeconvnode.resulttype_call_helper(c : tconverttype) : tnode;
     function ttypeconvnode.resulttype_call_helper(c : tconverttype) : tnode;
 {$ifdef fpc}
 {$ifdef fpc}
       const
       const
          resulttypeconvert : array[tconverttype] of pointer = (
          resulttypeconvert : array[tconverttype] of pointer = (
+          {none} nil,
           {equal} nil,
           {equal} nil,
           {not_possible} nil,
           {not_possible} nil,
           { string_2_string } @ttypeconvnode.resulttype_string_to_string,
           { string_2_string } @ttypeconvnode.resulttype_string_to_string,
@@ -1094,7 +1156,7 @@ implementation
           { real_2_real } @ttypeconvnode.resulttype_real_to_real,
           { real_2_real } @ttypeconvnode.resulttype_real_to_real,
           { int_2_real } @ttypeconvnode.resulttype_int_to_real,
           { int_2_real } @ttypeconvnode.resulttype_int_to_real,
           { real_2_currency } @ttypeconvnode.resulttype_real_to_currency,
           { real_2_currency } @ttypeconvnode.resulttype_real_to_currency,
-          { proc_2_procvar } nil,
+          { proc_2_procvar } @ttypeconvnode.resulttype_proc_to_procvar,
           { arrayconstructor_2_set } @ttypeconvnode.resulttype_arrayconstructor_to_set,
           { arrayconstructor_2_set } @ttypeconvnode.resulttype_arrayconstructor_to_set,
           { load_smallset } nil,
           { load_smallset } nil,
           { cord_2_pointer } @ttypeconvnode.resulttype_cord_to_pointer,
           { cord_2_pointer } @ttypeconvnode.resulttype_cord_to_pointer,
@@ -1103,12 +1165,12 @@ implementation
           { class_2_intf } nil,
           { class_2_intf } nil,
           { char_2_char } @ttypeconvnode.resulttype_char_to_char,
           { char_2_char } @ttypeconvnode.resulttype_char_to_char,
           { normal_2_smallset} nil,
           { normal_2_smallset} nil,
-          { dynarray_2_openarray} @resulttype_dynarray_to_openarray,
-          { pwchar_2_string} @resulttype_pwchar_to_string,
-          { variant_2_dynarray} @resulttype_variant_to_dynarray,
-          { dynarray_2_variant} @resulttype_dynarray_to_variant,
-          { variant_2_enum} @resulttype_variant_to_enum,
-          { enum_2_variant} @resulttype_enum_to_variant
+          { dynarray_2_openarray} @ttypeconvnode.resulttype_dynarray_to_openarray,
+          { pwchar_2_string} @ttypeconvnode.resulttype_pwchar_to_string,
+          { variant_2_dynarray} @ttypeconvnode.resulttype_variant_to_dynarray,
+          { dynarray_2_variant} @ttypeconvnode.resulttype_dynarray_to_variant,
+          { variant_2_enum} @ttypeconvnode.resulttype_variant_to_enum,
+          { enum_2_variant} @ttypeconvnode.resulttype_enum_to_variant
          );
          );
       type
       type
          tprocedureofobject = function : tnode of object;
          tprocedureofobject = function : tnode of object;
@@ -1183,7 +1245,8 @@ implementation
         { tp procvar support. Skip typecasts to record or set. Those
         { tp procvar support. Skip typecasts to record or set. Those
           convert on the procvar value. This is used to access the
           convert on the procvar value. This is used to access the
           fields of a methodpointer }
           fields of a methodpointer }
-        if not(resulttype.def.deftype in [recorddef,setdef]) then
+        if not(nf_load_procvar in flags) and
+           not(resulttype.def.deftype in [recorddef,setdef]) then
           maybe_call_procvar(left,true);
           maybe_call_procvar(left,true);
 
 
         { convert array constructors to sets, because there is no conversion
         { convert array constructors to sets, because there is no conversion
@@ -1195,242 +1258,229 @@ implementation
             resulttypepass(left);
             resulttypepass(left);
           end;
           end;
 
 
-        cdoptions:=[cdo_check_operator,cdo_allow_variant];
-        if nf_explicit in flags then
-          include(cdoptions,cdo_explicit);
-        if nf_internal in flags then
-          include(cdoptions,cdo_internal);
-        eq:=compare_defs_ext(left.resulttype.def,resulttype.def,left.nodetype,convtype,aprocdef,cdoptions);
-        case eq of
-          te_exact,
-          te_equal :
-            begin
-              { because is_equal only checks the basetype for sets we need to
-                check here if we are loading a smallset into a normalset }
-              if (resulttype.def.deftype=setdef) and
-                 (left.resulttype.def.deftype=setdef) and
-                 ((tsetdef(resulttype.def).settype = smallset) xor
-                  (tsetdef(left.resulttype.def).settype = smallset)) then
+        if convtype=tc_none then
+          begin
+            cdoptions:=[cdo_check_operator,cdo_allow_variant];
+            if nf_explicit in flags then
+              include(cdoptions,cdo_explicit);
+            if nf_internal in flags then
+              include(cdoptions,cdo_internal);
+            eq:=compare_defs_ext(left.resulttype.def,resulttype.def,left.nodetype,convtype,aprocdef,cdoptions);
+            case eq of
+              te_exact,
+              te_equal :
                 begin
                 begin
-                  { constant sets can be converted by changing the type only }
-                  if (left.nodetype=setconstn) then
-                   begin
-                     left.resulttype:=resulttype;
-                     result:=left;
-                     left:=nil;
-                     exit;
-                   end;
+                  { because is_equal only checks the basetype for sets we need to
+                    check here if we are loading a smallset into a normalset }
+                  if (resulttype.def.deftype=setdef) and
+                     (left.resulttype.def.deftype=setdef) and
+                     ((tsetdef(resulttype.def).settype = smallset) xor
+                      (tsetdef(left.resulttype.def).settype = smallset)) then
+                    begin
+                      { constant sets can be converted by changing the type only }
+                      if (left.nodetype=setconstn) then
+                       begin
+                         left.resulttype:=resulttype;
+                         result:=left;
+                         left:=nil;
+                         exit;
+                       end;
 
 
-                  if (tsetdef(resulttype.def).settype <> smallset) then
-                   convtype:=tc_load_smallset
+                      if (tsetdef(resulttype.def).settype <> smallset) then
+                       convtype:=tc_load_smallset
+                      else
+                       convtype := tc_normal_2_smallset;
+                      exit;
+                    end
                   else
                   else
-                   convtype := tc_normal_2_smallset;
-                  exit;
-                end
-              else
-               begin
-                 { Only leave when there is no conversion to do.
-                   We can still need to call a conversion routine,
-                   like the routine to convert a stringconstnode }
-                 if convtype in [tc_equal,tc_not_possible] then
-                  begin
-                    left.resulttype:=resulttype;
-                    result:=left;
-                    left:=nil;
-                    exit;
-                  end;
-               end;
-            end;
-
-          te_convert_l1,
-          te_convert_l2,
-          te_convert_l3 :
-            begin
-              { nothing to do }
-            end;
-
-          te_convert_operator :
-            begin
-              include(current_procinfo.flags,pi_do_call);
-              inc(aprocdef.procsym.refs);
-              hp:=ccallnode.create(ccallparanode.create(left,nil),Tprocsym(aprocdef.procsym),nil,nil,[]);
-              { tell explicitly which def we must use !! (PM) }
-              tcallnode(hp).procdefinition:=aprocdef;
-              left:=nil;
-              result:=hp;
-              exit;
-            end;
-
-          te_incompatible :
-            begin
-              { Procedures have a resulttype.def of voiddef and functions of their
-                own resulttype.def. They will therefore always be incompatible with
-                a procvar. Because isconvertable cannot check for procedures we
-                use an extra check for them.}
-              if (m_tp_procvar in aktmodeswitches) and
-                 (resulttype.def.deftype=procvardef) then
-               begin
-                 if is_procsym_load(left) then
-                  begin
-                    if (left.nodetype<>addrn) then
-                     begin
-                       convtype:=tc_proc_2_procvar;
-                       { Now check if the procedure we are going to assign to
-                         the procvar, is compatible with the procvar's type }
-                       if not(nf_explicit in flags) and
-                          (proc_to_procvar_equal(tprocsym(tloadnode(left).symtableentry).first_procdef,
-                                                 tprocvardef(resulttype.def),true)=te_incompatible) then
-                         IncompatibleTypes(tprocsym(tloadnode(left).symtableentry).first_procdef,resulttype.def);
-                       exit;
-                     end;
-                  end
-                 else
-                  if (left.nodetype=calln) and
-                     (tcallnode(left).para_count=0) then
                    begin
                    begin
-                     if assigned(tcallnode(left).right) then
+                     { Only leave when there is no conversion to do.
+                       We can still need to call a conversion routine,
+                       like the routine to convert a stringconstnode }
+                     if convtype in [tc_equal,tc_not_possible] then
                       begin
                       begin
-                        { this is already a procvar, if it is really equal
-                          is checked below }
-                        convtype:=tc_equal;
-                        hp:=tcallnode(left).right.getcopy;
-                        currprocdef:=tprocdef(hp.resulttype.def);
-                      end
-                     else
-                      begin
-                        convtype:=tc_proc_2_procvar;
-                        currprocdef:=Tprocsym(Tcallnode(left).symtableprocentry).search_procdef_byprocvardef(Tprocvardef(resulttype.def));
-                        hp:=cloadnode.create_procvar(tprocsym(tcallnode(left).symtableprocentry),
-                            currprocdef,tcallnode(left).symtableproc);
-                        if (tcallnode(left).symtableprocentry.owner.symtabletype=objectsymtable) then
-                         begin
-                           if assigned(tcallnode(left).methodpointer) then
-                             begin
-                               { Under certain circumstances the methodpointer is a loadvmtaddrn
-                                 which isn't possible if it is used as a method pointer, so
-                                 fix this.
-                                 If you change this, ensure that tests/tbs/tw2669.pp still works }
-                               if tcallnode(left).methodpointer.nodetype=loadvmtaddrn then
-                                 tloadnode(hp).set_mp(tloadvmtaddrnode(tcallnode(left).methodpointer).left.getcopy)
-                               else
-                                 tloadnode(hp).set_mp(tcallnode(left).methodpointer.getcopy);
-                             end
-                           else
-                             tloadnode(hp).set_mp(load_self_node);
-                         end;
-                        resulttypepass(hp);
+                        left.resulttype:=resulttype;
+                        result:=left;
+                        left:=nil;
+                        exit;
                       end;
                       end;
-                     left.free;
-                     left:=hp;
-                     { Now check if the procedure we are going to assign to
-                       the procvar, is compatible with the procvar's type }
-                     if not(nf_explicit in flags) and
-                        (proc_to_procvar_equal(currprocdef,
-                                               tprocvardef(resulttype.def),true)=te_incompatible) then
-                       IncompatibleTypes(left.resulttype.def,resulttype.def);
-                     exit;
                    end;
                    end;
-               end;
+                end;
 
 
-              { Handle explicit type conversions }
-              if nf_explicit in flags then
-               begin
-                 { do common tc_equal cast }
-                 convtype:=tc_equal;
+              te_convert_l1,
+              te_convert_l2,
+              te_convert_l3 :
+                begin
+                  { nothing to do }
+                end;
+
+              te_convert_operator :
+                begin
+                  include(current_procinfo.flags,pi_do_call);
+                  inc(aprocdef.procsym.refs);
+                  hp:=ccallnode.create(ccallparanode.create(left,nil),Tprocsym(aprocdef.procsym),nil,nil,[]);
+                  { tell explicitly which def we must use !! (PM) }
+                  tcallnode(hp).procdefinition:=aprocdef;
+                  left:=nil;
+                  result:=hp;
+                  exit;
+                end;
 
 
-                 { ordinal constants can be resized to 1,2,4,8 bytes }
-                 if (left.nodetype=ordconstn) then
+              te_incompatible :
+                begin
+                  { Procedures have a resulttype.def of voiddef and functions of their
+                    own resulttype.def. They will therefore always be incompatible with
+                    a procvar. Because isconvertable cannot check for procedures we
+                    use an extra check for them.}
+                  if (m_tp_procvar in aktmodeswitches) and
+                     (resulttype.def.deftype=procvardef) then
                    begin
                    begin
-                     { Insert typeconv for ordinal to the correct size first on left, after
-                       that the other conversion can be done }
-                     htype.reset;
-                     case longint(resulttype.def.size) of
-                       1 :
-                         htype:=s8inttype;
-                       2 :
-                         htype:=s16inttype;
-                       4 :
-                         htype:=s32inttype;
-                       8 :
-                         htype:=s64inttype;
-                     end;
-                     { we need explicit, because it can also be an enum }
-                     if assigned(htype.def) then
-                       inserttypeconv_internal(left,htype)
-                     else
-                       CGMessage2(type_e_illegal_type_conversion,left.resulttype.def.gettypename,resulttype.def.gettypename);
+                      if (left.nodetype=calln) and
+                         (tcallnode(left).para_count=0) then
+                       begin
+                         if assigned(tcallnode(left).right) then
+                          begin
+                            { this is already a procvar, if it is really equal
+                              is checked below }
+                            convtype:=tc_equal;
+                            hp:=tcallnode(left).right.getcopy;
+                            currprocdef:=tprocdef(hp.resulttype.def);
+                          end
+                         else
+                          begin
+                            convtype:=tc_proc_2_procvar;
+                            currprocdef:=Tprocsym(Tcallnode(left).symtableprocentry).search_procdef_byprocvardef(Tprocvardef(resulttype.def));
+                            hp:=cloadnode.create_procvar(tprocsym(tcallnode(left).symtableprocentry),
+                                currprocdef,tcallnode(left).symtableproc);
+                            if (tcallnode(left).symtableprocentry.owner.symtabletype=objectsymtable) then
+                             begin
+                               if assigned(tcallnode(left).methodpointer) then
+                                 begin
+                                   { Under certain circumstances the methodpointer is a loadvmtaddrn
+                                     which isn't possible if it is used as a method pointer, so
+                                     fix this.
+                                     If you change this, ensure that tests/tbs/tw2669.pp still works }
+                                   if tcallnode(left).methodpointer.nodetype=loadvmtaddrn then
+                                     tloadnode(hp).set_mp(tloadvmtaddrnode(tcallnode(left).methodpointer).left.getcopy)
+                                   else
+                                     tloadnode(hp).set_mp(tcallnode(left).methodpointer.getcopy);
+                                 end
+                               else
+                                 tloadnode(hp).set_mp(load_self_node);
+                             end;
+                            resulttypepass(hp);
+                          end;
+                         left.free;
+                         left:=hp;
+                         { Now check if the procedure we are going to assign to
+                           the procvar, is compatible with the procvar's type }
+                         if not(nf_explicit in flags) and
+                            (proc_to_procvar_equal(currprocdef,
+                                                   tprocvardef(resulttype.def),true)=te_incompatible) then
+                           IncompatibleTypes(left.resulttype.def,resulttype.def);
+                         exit;
+                       end;
                    end;
                    end;
 
 
-                 { check if the result could be in a register }
-                 if (not(tstoreddef(resulttype.def).is_intregable) and
-                     not(tstoreddef(resulttype.def).is_fpuregable)) or
-                    ((left.resulttype.def.deftype = floatdef) and
-                     (resulttype.def.deftype <> floatdef))  then
-                   make_not_regable(left);
-
-                 { class to class or object to object, with checkobject support }
-                 if (resulttype.def.deftype=objectdef) and
-                    (left.resulttype.def.deftype=objectdef) then
+                  { Handle explicit type conversions }
+                  if nf_explicit in flags then
                    begin
                    begin
-                     if (cs_check_object in aktlocalswitches) then
-                      begin
-                        if is_class_or_interface(resulttype.def) then
-                         begin
-                           { we can translate the typeconvnode to 'as' when
-                             typecasting to a class or interface }
-                           hp:=casnode.create(left,cloadvmtaddrnode.create(ctypenode.create(resulttype)));
-                           left:=nil;
-                           result:=hp;
-                           exit;
+                     { do common tc_equal cast }
+                     convtype:=tc_equal;
+
+                     { ordinal constants can be resized to 1,2,4,8 bytes }
+                     if (left.nodetype=ordconstn) then
+                       begin
+                         { Insert typeconv for ordinal to the correct size first on left, after
+                           that the other conversion can be done }
+                         htype.reset;
+                         case longint(resulttype.def.size) of
+                           1 :
+                             htype:=s8inttype;
+                           2 :
+                             htype:=s16inttype;
+                           4 :
+                             htype:=s32inttype;
+                           8 :
+                             htype:=s64inttype;
                          end;
                          end;
-                      end
-                     else
-                      begin
-                        { check if the types are related }
-                        if not(nf_internal in flags) and
-                           (not(tobjectdef(left.resulttype.def).is_related(tobjectdef(resulttype.def)))) and
-                           (not(tobjectdef(resulttype.def).is_related(tobjectdef(left.resulttype.def)))) then
+                         { we need explicit, because it can also be an enum }
+                         if assigned(htype.def) then
+                           inserttypeconv_internal(left,htype)
+                         else
+                           CGMessage2(type_e_illegal_type_conversion,left.resulttype.def.gettypename,resulttype.def.gettypename);
+                       end;
+
+                     { check if the result could be in a register }
+                     if (not(tstoreddef(resulttype.def).is_intregable) and
+                         not(tstoreddef(resulttype.def).is_fpuregable)) or
+                        ((left.resulttype.def.deftype = floatdef) and
+                         (resulttype.def.deftype <> floatdef))  then
+                       make_not_regable(left);
+
+                     { class to class or object to object, with checkobject support }
+                     if (resulttype.def.deftype=objectdef) and
+                        (left.resulttype.def.deftype=objectdef) then
+                       begin
+                         if (cs_check_object in aktlocalswitches) then
                           begin
                           begin
-                            { Give an error when typecasting class to interface, this is compatible
-                              with delphi }
-                            if is_interface(resulttype.def) and
-                               not is_interface(left.resulttype.def) then
-                              CGMessage2(type_e_classes_not_related,
-                                FullTypeName(left.resulttype.def,resulttype.def),
-                                FullTypeName(resulttype.def,left.resulttype.def))
-                            else
-                              CGMessage2(type_w_classes_not_related,
-                                FullTypeName(left.resulttype.def,resulttype.def),
-                                FullTypeName(resulttype.def,left.resulttype.def))
+                            if is_class_or_interface(resulttype.def) then
+                             begin
+                               { we can translate the typeconvnode to 'as' when
+                                 typecasting to a class or interface }
+                               hp:=casnode.create(left,cloadvmtaddrnode.create(ctypenode.create(resulttype)));
+                               left:=nil;
+                               result:=hp;
+                               exit;
+                             end;
+                          end
+                         else
+                          begin
+                            { check if the types are related }
+                            if not(nf_internal in flags) and
+                               (not(tobjectdef(left.resulttype.def).is_related(tobjectdef(resulttype.def)))) and
+                               (not(tobjectdef(resulttype.def).is_related(tobjectdef(left.resulttype.def)))) then
+                              begin
+                                { Give an error when typecasting class to interface, this is compatible
+                                  with delphi }
+                                if is_interface(resulttype.def) and
+                                   not is_interface(left.resulttype.def) then
+                                  CGMessage2(type_e_classes_not_related,
+                                    FullTypeName(left.resulttype.def,resulttype.def),
+                                    FullTypeName(resulttype.def,left.resulttype.def))
+                                else
+                                  CGMessage2(type_w_classes_not_related,
+                                    FullTypeName(left.resulttype.def,resulttype.def),
+                                    FullTypeName(resulttype.def,left.resulttype.def))
+                              end;
                           end;
                           end;
-                      end;
-                   end
+                       end
 
 
+                      else
+                       begin
+                         { only if the same size or formal def }
+                         if not(
+                                (left.resulttype.def.deftype=formaldef) or
+                                (
+                                 not(is_open_array(left.resulttype.def)) and
+                                 (left.resulttype.def.size=resulttype.def.size)
+                                ) or
+                                (
+                                 is_void(left.resulttype.def)  and
+                                 (left.nodetype=derefn)
+                                )
+                               ) then
+                           CGMessage2(type_e_illegal_type_conversion,left.resulttype.def.gettypename,resulttype.def.gettypename);
+                       end;
+                   end
                   else
                   else
-                   begin
-                     { only if the same size or formal def }
-                     if not(
-                            (left.resulttype.def.deftype=formaldef) or
-                            (
-                             not(is_open_array(left.resulttype.def)) and
-                             (left.resulttype.def.size=resulttype.def.size)
-                            ) or
-                            (
-                             is_void(left.resulttype.def)  and
-                             (left.nodetype=derefn)
-                            )
-                           ) then
-                       CGMessage2(type_e_illegal_type_conversion,left.resulttype.def.gettypename,resulttype.def.gettypename);
-                   end;
-               end
+                   IncompatibleTypes(left.resulttype.def,resulttype.def);
+                end;
+
               else
               else
-               IncompatibleTypes(left.resulttype.def,resulttype.def);
+                internalerror(200211231);
             end;
             end;
-
-          else
-            internalerror(200211231);
-        end;
-
+          end;
         { Give hint or warning for unportable code, exceptions are
         { Give hint or warning for unportable code, exceptions are
            - typecasts from constants
            - typecasts from constants
            - void }
            - void }
@@ -1753,19 +1803,19 @@ implementation
     function ttypeconvnode.first_proc_to_procvar : tnode;
     function ttypeconvnode.first_proc_to_procvar : tnode;
       begin
       begin
          first_proc_to_procvar:=nil;
          first_proc_to_procvar:=nil;
-         if assigned(tunarynode(left).left) then
+         if tabstractprocdef(resulttype.def).is_addressonly then
           begin
           begin
-            if (left.expectloc<>LOC_CREFERENCE) then
-              CGMessage(parser_e_illegal_expression);
             registersint:=left.registersint;
             registersint:=left.registersint;
-            expectloc:=left.expectloc
+            if registersint<1 then
+              registersint:=1;
+            expectloc:=LOC_REGISTER;
           end
           end
          else
          else
           begin
           begin
+            if not(left.expectloc in [LOC_CREFERENCE,LOC_REFERENCE]) then
+              CGMessage(parser_e_illegal_expression);
             registersint:=left.registersint;
             registersint:=left.registersint;
-            if registersint<1 then
-              registersint:=1;
-            expectloc:=LOC_REGISTER;
+            expectloc:=left.expectloc
           end
           end
       end;
       end;
 
 
@@ -1920,6 +1970,7 @@ implementation
 
 
       const
       const
          firstconvert : array[tconverttype] of pointer = (
          firstconvert : array[tconverttype] of pointer = (
+           nil, { none }
            @ttypeconvnode._first_nothing, {equal}
            @ttypeconvnode._first_nothing, {equal}
            @ttypeconvnode._first_nothing, {not_possible}
            @ttypeconvnode._first_nothing, {not_possible}
            nil, { removed in resulttype_string_to_string }
            nil, { removed in resulttype_string_to_string }
@@ -2151,44 +2202,44 @@ implementation
 
 
 
 
     procedure ttypeconvnode.second_call_helper(c : tconverttype);
     procedure ttypeconvnode.second_call_helper(c : tconverttype);
-{$ifdef fpc}
       const
       const
          secondconvert : array[tconverttype] of pointer = (
          secondconvert : array[tconverttype] of pointer = (
-           @_second_nothing, {equal}
-           @_second_nothing, {not_possible}
-           @_second_nothing, {second_string_to_string, handled in resulttype pass }
-           @_second_char_to_string,
-           @_second_nothing, {char_to_charray}
-           @_second_nothing, { pchar_to_string, handled in resulttype pass }
-           @_second_nothing, {cchar_to_pchar}
-           @_second_cstring_to_pchar,
-           @_second_ansistring_to_pchar,
-           @_second_string_to_chararray,
-           @_second_nothing, { chararray_to_string, handled in resulttype pass }
-           @_second_array_to_pointer,
-           @_second_pointer_to_array,
-           @_second_int_to_int,
-           @_second_int_to_bool,
-           @_second_bool_to_bool,
-           @_second_bool_to_int,
-           @_second_real_to_real,
-           @_second_int_to_real,
-           @_second_nothing, { real_to_currency, handled in resulttype pass }
-           @_second_proc_to_procvar,
-           @_second_nothing, { arrayconstructor_to_set }
-           @_second_nothing, { second_load_smallset, handled in first pass }
-           @_second_cord_to_pointer,
-           @_second_nothing, { interface 2 string }
-           @_second_nothing, { interface 2 guid   }
-           @_second_class_to_intf,
-           @_second_char_to_char,
-           @_second_nothing,  { normal_2_smallset }
-           @_second_nothing,  { dynarray_2_openarray }
-           @_second_nothing,  { pwchar_2_string }
-           @_second_nothing,  { variant_2_dynarray }
-           @_second_nothing,  { dynarray_2_variant}
-           @_second_nothing,  { variant_2_enum }
-           @_second_nothing   { enum_2_variant }
+           @ttypeconvnode._second_nothing, {none}
+           @ttypeconvnode._second_nothing, {equal}
+           @ttypeconvnode._second_nothing, {not_possible}
+           @ttypeconvnode._second_nothing, {second_string_to_string, handled in resulttype pass }
+           @ttypeconvnode._second_char_to_string,
+           @ttypeconvnode._second_nothing, {char_to_charray}
+           @ttypeconvnode._second_nothing, { pchar_to_string, handled in resulttype pass }
+           @ttypeconvnode._second_nothing, {cchar_to_pchar}
+           @ttypeconvnode._second_cstring_to_pchar,
+           @ttypeconvnode._second_ansistring_to_pchar,
+           @ttypeconvnode._second_string_to_chararray,
+           @ttypeconvnode._second_nothing, { chararray_to_string, handled in resulttype pass }
+           @ttypeconvnode._second_array_to_pointer,
+           @ttypeconvnode._second_pointer_to_array,
+           @ttypeconvnode._second_int_to_int,
+           @ttypeconvnode._second_int_to_bool,
+           @ttypeconvnode._second_bool_to_bool,
+           @ttypeconvnode._second_bool_to_int,
+           @ttypeconvnode._second_real_to_real,
+           @ttypeconvnode._second_int_to_real,
+           @ttypeconvnode._second_nothing, { real_to_currency, handled in resulttype pass }
+           @ttypeconvnode._second_proc_to_procvar,
+           @ttypeconvnode._second_nothing, { arrayconstructor_to_set }
+           @ttypeconvnode._second_nothing, { second_load_smallset, handled in first pass }
+           @ttypeconvnode._second_cord_to_pointer,
+           @ttypeconvnode._second_nothing, { interface 2 string }
+           @ttypeconvnode._second_nothing, { interface 2 guid   }
+           @ttypeconvnode._second_class_to_intf,
+           @ttypeconvnode._second_char_to_char,
+           @ttypeconvnode._second_nothing,  { normal_2_smallset }
+           @ttypeconvnode._second_nothing,  { dynarray_2_openarray }
+           @ttypeconvnode._second_nothing,  { pwchar_2_string }
+           @ttypeconvnode._second_nothing,  { variant_2_dynarray }
+           @ttypeconvnode._second_nothing,  { dynarray_2_variant}
+           @ttypeconvnode._second_nothing,  { variant_2_enum }
+           @ttypeconvnode._second_nothing   { enum_2_variant }
          );
          );
       type
       type
          tprocedureofobject = procedure of object;
          tprocedureofobject = procedure of object;
@@ -2206,46 +2257,7 @@ implementation
          r.obj:=self;
          r.obj:=self;
          tprocedureofobject(r)();
          tprocedureofobject(r)();
       end;
       end;
-{$else fpc}
-     begin
-        case c of
-          tc_equal,
-          tc_not_possible,
-          tc_string_2_string : second_nothing;
-          tc_char_2_string : second_char_to_string;
-          tc_char_2_chararray : second_nothing;
-          tc_pchar_2_string : second_nothing;
-          tc_cchar_2_pchar : second_nothing;
-          tc_cstring_2_pchar : second_cstring_to_pchar;
-          tc_ansistring_2_pchar : second_ansistring_to_pchar;
-          tc_string_2_chararray : second_string_to_chararray;
-          tc_chararray_2_string : second_nothing;
-          tc_array_2_pointer : second_array_to_pointer;
-          tc_pointer_2_array : second_pointer_to_array;
-          tc_int_2_int : second_int_to_int;
-          tc_int_2_bool : second_int_to_bool;
-          tc_bool_2_bool : second_bool_to_bool;
-          tc_bool_2_int : second_bool_to_int;
-          tc_real_2_real : second_real_to_real;
-          tc_int_2_real : second_int_to_real;
-          tc_real_2_currency : second_nothing;
-          tc_proc_2_procvar : second_proc_to_procvar;
-          tc_arrayconstructor_2_set : second_nothing;
-          tc_load_smallset : second_nothing;
-          tc_cord_2_pointer : second_cord_to_pointer;
-          tc_intf_2_string : second_nothing;
-          tc_intf_2_guid : second_nothing;
-          tc_class_2_intf : second_class_to_intf;
-          tc_char_2_char : second_char_to_char;
-          tc_normal_2_smallset : second_nothing;
-          tc_dynarray_2_openarray : second_nothing;
-          tc_pwchar_2_string : second_nothing;
-          tc_variant_2_dynarray : second_nothing;
-          tc_dynarray_2_variant : second_nothing;
-          else internalerror(2002101101);
-        end;
-     end;
-{$endif fpc}
+
 
 
 {*****************************************************************************
 {*****************************************************************************
                                 TISNODE
                                 TISNODE
@@ -2486,7 +2498,13 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.165  2004-12-05 12:15:11  florian
+  Revision 1.166  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.165  2004/12/05 12:15:11  florian
     * fixed compiler side of variant <-> dyn. array conversion
     * fixed compiler side of variant <-> dyn. array conversion
 
 
   Revision 1.164  2004/11/26 22:34:28  peter
   Revision 1.164  2004/11/26 22:34:28  peter

+ 9 - 3
compiler/ninl.pas

@@ -424,7 +424,7 @@ implementation
                 { assign the address of the file to the temp }
                 { assign the address of the file to the temp }
                 addstatement(newstatement,
                 addstatement(newstatement,
                   cassignmentnode.create(ctemprefnode.create(filetemp),
                   cassignmentnode.create(ctemprefnode.create(filetemp),
-                    caddrnode.create(filepara.left)));
+                    caddrnode.create_internal(filepara.left)));
                 resulttypepass(newstatement.left);
                 resulttypepass(newstatement.left);
                 { create a new fileparameter as follows: file_type(temp^)    }
                 { create a new fileparameter as follows: file_type(temp^)    }
                 { (so that we pass the value and not the address of the temp }
                 { (so that we pass the value and not the address of the temp }
@@ -2160,7 +2160,7 @@ implementation
                        tempnode := ctempcreatenode.create(voidpointertype,voidpointertype.def.size,tt_persistent,true);
                        tempnode := ctempcreatenode.create(voidpointertype,voidpointertype.def.size,tt_persistent,true);
                        addstatement(newstatement,tempnode);
                        addstatement(newstatement,tempnode);
                        addstatement(newstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
                        addstatement(newstatement,cassignmentnode.create(ctemprefnode.create(tempnode),
-                         caddrnode.create(tcallparanode(left).left.getcopy)));
+                         caddrnode.create_internal(tcallparanode(left).left.getcopy)));
                        hp := cderefnode.create(ctemprefnode.create(tempnode));
                        hp := cderefnode.create(ctemprefnode.create(tempnode));
                        inserttypeconv_internal(hp,tcallparanode(left).left.resulttype);
                        inserttypeconv_internal(hp,tcallparanode(left).left.resulttype);
                      end
                      end
@@ -2463,7 +2463,13 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.155  2004-11-26 22:33:00  peter
+  Revision 1.156  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.155  2004/11/26 22:33:00  peter
     * fixed read temp for result
     * fixed read temp for result
 
 
   Revision 1.154  2004/11/21 21:27:31  peter
   Revision 1.154  2004/11/21 21:27:31  peter

+ 8 - 2
compiler/nld.pas

@@ -595,7 +595,7 @@ implementation
         if is_dynamic_array(left.resulttype.def) and
         if is_dynamic_array(left.resulttype.def) and
            (right.nodetype=niln) then
            (right.nodetype=niln) then
          begin
          begin
-           hp:=ccallparanode.create(caddrnode.create
+           hp:=ccallparanode.create(caddrnode.create_internal
                    (crttinode.create(tstoreddef(left.resulttype.def),initrtti)),
                    (crttinode.create(tstoreddef(left.resulttype.def),initrtti)),
                ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),nil));
                ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),nil));
            result := ccallnode.createintern('fpc_dynarray_clear',hp);
            result := ccallnode.createintern('fpc_dynarray_clear',hp);
@@ -1172,7 +1172,13 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.139  2004-11-08 22:09:59  peter
+  Revision 1.140  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.139  2004/11/08 22:09:59  peter
     * tvarsym splitted
     * tvarsym splitted
 
 
   Revision 1.138  2004/11/02 12:55:16  peter
   Revision 1.138  2004/11/02 12:55:16  peter

+ 83 - 143
compiler/nmem.pas

@@ -56,6 +56,7 @@ interface
           getprocvardef : tprocvardef;
           getprocvardef : tprocvardef;
           getprocvardefderef : tderef;
           getprocvardefderef : tderef;
           constructor create(l : tnode);virtual;
           constructor create(l : tnode);virtual;
+          constructor create_internal(l : tnode); virtual;
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
           constructor ppuload(t:tnodetype;ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure ppuwrite(ppufile:tcompilerppufile);override;
           procedure mark_write;override;
           procedure mark_write;override;
@@ -127,7 +128,7 @@ implementation
 
 
     uses
     uses
       globtype,systems,
       globtype,systems,
-      cutils,cclasses,verbose,globals,
+      cutils,verbose,globals,
       symconst,symbase,defutil,defcmp,
       symconst,symbase,defutil,defcmp,
       nbas,nutils,
       nbas,nutils,
       htypechk,pass_1,ncal,nld,ncon,ncnv,cgbase,procinfo
       htypechk,pass_1,ncal,nld,ncon,ncnv,cgbase,procinfo
@@ -255,6 +256,13 @@ implementation
       end;
       end;
 
 
 
 
+    constructor taddrnode.create_internal(l : tnode);
+      begin
+        self.create(l);
+        include(flags,nf_internal);
+      end;
+
+
     constructor taddrnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
     constructor taddrnode.ppuload(t:tnodetype;ppufile:tcompilerppufile);
       begin
       begin
         inherited ppuload(t,ppufile);
         inherited ppuload(t,ppufile);
@@ -301,29 +309,11 @@ implementation
       end;
       end;
 
 
 
 
-    procedure copyparasym(p:TNamedIndexItem;arg:pointer);
-      var
-        newparast : tsymtable absolute arg;
-        vs : tparavarsym;
-      begin
-        if tsym(p).typ<>paravarsym then
-          exit;
-        with tparavarsym(p) do
-          begin
-            vs:=tparavarsym.create(realname,paranr,varspez,vartype);
-            vs.varoptions:=varoptions;
-//            vs.paraloc[callerside]:=paraloc[callerside].getcopy;
-//            vs.paraloc[callerside]:=paraloc[callerside].getcopy;
-            vs.defaultconstsym:=defaultconstsym;
-            newparast.insert(vs);
-          end;
-      end;
-
-
     function taddrnode.det_resulttype:tnode;
     function taddrnode.det_resulttype:tnode;
       var
       var
          hp  : tnode;
          hp  : tnode;
-         hp3 : tabstractprocdef;
+         hsym : tfieldvarsym;
+         isprocvar : boolean;
       begin
       begin
         result:=nil;
         result:=nil;
         resulttypepass(left);
         resulttypepass(left);
@@ -340,137 +330,94 @@ implementation
            exit;
            exit;
          end;
          end;
 
 
-        { tp @procvar support (type of @procvar is a void pointer)
-          Note: we need to leave the addrn in the tree,
-          else we can't see the difference between @procvar and procvar.
-          we set the procvarload flag so a secondpass does nothing for
-          this node (PFV) }
-        if (m_tp_procvar in aktmodeswitches) then
-         begin
-           case left.nodetype of
-             calln :
-               begin
-                 { a load of a procvar can't have parameters }
-                 if assigned(tcallnode(left).left) then
-                   CGMessage(parser_e_illegal_expression);
-                 { is it a procvar? }
-                 hp:=tcallnode(left).right;
-                 if assigned(hp) then
-                   begin
-                     { remove calln node }
-                     tcallnode(left).right:=nil;
-                     left.free;
-                     left:=hp;
-                     include(flags,nf_procvarload);
-                   end;
-               end;
-             loadn,
-             subscriptn,
-             typeconvn,
-             vecn,
-             derefn :
-               begin
-                 if left.resulttype.def.deftype=procvardef then
-                   include(flags,nf_procvarload);
-               end;
-           end;
-           if nf_procvarload in flags then
-            begin
-              resulttype:=voidpointertype;
-              exit;
-            end;
-         end;
-
-        { proc 2 procvar ? }
-        if left.nodetype=calln then
-         { if it were a valid construct, the addr node would already have }
-         { been removed in the parser. This happens for (in FPC mode)     }
-         { procvar1 := @procvar2(parameters);                             }
-         CGMessage(parser_e_illegal_expression)
-        else
-         if (left.nodetype=loadn) and (tloadnode(left).symtableentry.typ=procsym) then
+        { Handle @proc special, also @procvar in tp-mode needs
+          special handling }
+        if (left.resulttype.def.deftype=procdef) or
+           ((left.resulttype.def.deftype=procvardef) and
+            (m_tp_procvar in aktmodeswitches)) then
           begin
           begin
-            { result is a procedure variable }
-            { No, to be TP compatible, you must return a voidpointer to
-              the procedure that is stored in the procvar.}
-            if not(m_tp_procvar in aktmodeswitches) then
+            isprocvar:=(left.resulttype.def.deftype=procvardef);
+
+            if not isprocvar then
+              begin
+                left:=ctypeconvnode.create_proc_to_procvar(left);
+                resulttypepass(left);
+              end;
+
+            { In tp procvar mode the result is always a voidpointer. Insert
+              a typeconversion to voidpointer. For methodpointers we need
+              to load the proc field }
+            if (m_tp_procvar in aktmodeswitches) then
               begin
               begin
-                 if assigned(getprocvardef) and
-                    (tprocsym(tloadnode(left).symtableentry).procdef_count>1) then
+                if tabstractprocdef(left.resulttype.def).is_addressonly then
                   begin
                   begin
-                    hp3:=tprocsym(tloadnode(left).symtableentry).search_procdef_byprocvardef(getprocvardef);
-                    if not assigned(hp3)  then
-                     begin
-                       IncompatibleTypes(tprocsym(tloadnode(left).symtableentry).first_procdef,getprocvardef);
-                       exit;
-                     end;
+                    result:=ctypeconvnode.create_internal(left,voidpointertype);
+                    include(result.flags,nf_load_procvar);
+                    left:=nil;
                   end
                   end
-                 else
-                  hp3:=tabstractprocdef(tprocsym(tloadnode(left).symtableentry).first_procdef);
-
-                 { create procvardef }
-                 resulttype.setdef(tprocvardef.create(hp3.parast.symtablelevel));
-                 tprocvardef(resulttype.def).proctypeoption:=hp3.proctypeoption;
-                 tprocvardef(resulttype.def).proccalloption:=hp3.proccalloption;
-                 tprocvardef(resulttype.def).procoptions:=hp3.procoptions;
-                 tprocvardef(resulttype.def).rettype:=hp3.rettype;
-
-                 { method ? then set the methodpointer flag }
-                 if (hp3.owner.symtabletype=objectsymtable) then
-                   include(tprocvardef(resulttype.def).procoptions,po_methodpointer);
-
-                 { only need the address of the method? this is needed
-                   for @tobject.create }
-                 if assigned(tloadnode(left).left) then
-                   include(flags,nf_procvarload)
-                 else
-                   include(tprocvardef(resulttype.def).procoptions,po_addressonly);
-
-                 { Add parameters use only references, we don't need to keep the
-                   parast. We use the parast from the original function to calculate
-                   our parameter data and reset it afterwards }
-                 hp3.parast.foreach_static(@copyparasym,tprocvardef(resulttype.def).parast);
-                 tprocvardef(resulttype.def).calcparas;
+                else
+                  begin
+                    { For procvars we need to return the proc field of the
+                      methodpointer }
+                    if isprocvar then
+                      begin
+                        { find proc field in methodpointer record }
+                        hsym:=tfieldvarsym(trecorddef(methodpointertype.def).symtable.search('proc'));
+                        if not assigned(hsym) then
+                          internalerror(200412041);
+                        { Load tmehodpointer(left).proc }
+                        result:=csubscriptnode.create(
+                                     hsym,
+                                     ctypeconvnode.create_internal(left,methodpointertype));
+                        left:=nil;
+                      end
+                    else
+                      CGMessage(type_e_variable_id_expected);
+                  end;
               end
               end
             else
             else
               begin
               begin
-                if assigned(tloadnode(left).left) then
-                  CGMessage(parser_e_illegal_expression);
-                resulttype:=voidpointertype;
+                { Return the typeconvn only }
+                result:=left;
+                left:=nil;
               end;
               end;
           end
           end
         else
         else
           begin
           begin
             { what are we getting the address from an absolute sym? }
             { what are we getting the address from an absolute sym? }
             hp:=left;
             hp:=left;
-            while assigned(hp) and (hp.nodetype in [vecn,derefn,subscriptn]) do
-             hp:=tunarynode(hp).left;
+            while assigned(hp) and (hp.nodetype in [typeconvn,vecn,derefn,subscriptn]) do
+              hp:=tunarynode(hp).left;
+            if not assigned(hp) then
+              internalerror(200412042);
 {$ifdef i386}
 {$ifdef i386}
-            if assigned(hp) and
-               (hp.nodetype=loadn) and
+            if (hp.nodetype=loadn) and
                ((tloadnode(hp).symtableentry.typ=absolutevarsym) and
                ((tloadnode(hp).symtableentry.typ=absolutevarsym) and
-                tabsolutevarsym(tloadnode(hp).symtableentry).absseg) then
-             begin
-               if not(nf_typedaddr in flags) then
-                 resulttype:=voidfarpointertype
-               else
-                 resulttype.setdef(tpointerdef.createfar(left.resulttype));
-             end
+               tabsolutevarsym(tloadnode(hp).symtableentry).absseg) then
+              begin
+                if not(nf_typedaddr in flags) then
+                  resulttype:=voidfarpointertype
+                else
+                  resulttype.setdef(tpointerdef.createfar(left.resulttype));
+              end
             else
             else
 {$endif i386}
 {$endif i386}
-             begin
-               if not(nf_typedaddr in flags) then
-                 resulttype:=voidpointertype
-               else
-                 resulttype.setdef(tpointerdef.create(left.resulttype));
-             end;
+              if (nf_internal in flags) or
+                 valid_for_addr(left) then
+                begin
+                  if not(nf_typedaddr in flags) then
+                    resulttype:=voidpointertype
+                  else
+                    resulttype.setdef(tpointerdef.create(left.resulttype));
+                end
+            else
+              CGMessage(type_e_variable_id_expected);
           end;
           end;
 
 
          { this is like the function addr }
          { this is like the function addr }
          inc(parsing_para_level);
          inc(parsing_para_level);
          set_varstate(left,vs_used,false);
          set_varstate(left,vs_used,false);
          dec(parsing_para_level);
          dec(parsing_para_level);
-
       end;
       end;
 
 
 
 
@@ -481,19 +428,6 @@ implementation
          if codegenerror then
          if codegenerror then
           exit;
           exit;
 
 
-         if nf_procvarload in flags then
-          begin
-            registersint:=left.registersint;
-            registersfpu:=left.registersfpu;
-{$ifdef SUPPORT_MMX}
-            registersmmx:=left.registersmmx;
-{$endif SUPPORT_MMX}
-            if registersint<1 then
-             registersint:=1;
-            expectloc:=left.expectloc;
-            exit;
-          end;
-
          { we should allow loc_mem for @string }
          { we should allow loc_mem for @string }
          if not(left.expectloc in [LOC_CREFERENCE,LOC_REFERENCE]) then
          if not(left.expectloc in [LOC_CREFERENCE,LOC_REFERENCE]) then
            begin
            begin
@@ -997,7 +931,13 @@ begin
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.91  2004-11-29 17:32:56  peter
+  Revision 1.92  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.91  2004/11/29 17:32:56  peter
     * prevent some IEs with delphi methodpointers
     * prevent some IEs with delphi methodpointers
 
 
   Revision 1.90  2004/11/26 22:33:24  peter
   Revision 1.90  2004/11/26 22:33:24  peter

+ 8 - 2
compiler/node.pas

@@ -205,7 +205,6 @@ interface
          nf_isproperty,
          nf_isproperty,
 
 
          { taddrnode }
          { taddrnode }
-         nf_procvarload,
          nf_typedaddr,
          nf_typedaddr,
 
 
          { tderefnode }
          { tderefnode }
@@ -235,6 +234,7 @@ interface
          { ttypeconvnode }
          { ttypeconvnode }
          nf_explicit,
          nf_explicit,
          nf_internal,  { no warnings/hints generated }
          nf_internal,  { no warnings/hints generated }
+         nf_load_procvar,
 
 
          { tinlinenode }
          { tinlinenode }
          nf_inlineconst,
          nf_inlineconst,
@@ -1139,7 +1139,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.91  2004-12-02 19:26:15  peter
+  Revision 1.92  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.91  2004/12/02 19:26:15  peter
     * disable pass2inline
     * disable pass2inline
 
 
   Revision 1.90  2004/11/02 12:55:16  peter
   Revision 1.90  2004/11/02 12:55:16  peter

+ 13 - 7
compiler/nutils.pas

@@ -417,11 +417,11 @@ implementation
           begin
           begin
             result:=ccallnode.createintern('fpc_initialize',
             result:=ccallnode.createintern('fpc_initialize',
                   ccallparanode.create(
                   ccallparanode.create(
-                      caddrnode.create(
+                      caddrnode.create_internal(
                           crttinode.create(
                           crttinode.create(
                               tstoreddef(p.resulttype.def),initrtti)),
                               tstoreddef(p.resulttype.def),initrtti)),
                   ccallparanode.create(
                   ccallparanode.create(
-                      caddrnode.create(p),
+                      caddrnode.create_internal(p),
                   nil)));
                   nil)));
           end;
           end;
       end;
       end;
@@ -433,11 +433,11 @@ implementation
           resulttypepass(p);
           resulttypepass(p);
         result:=ccallnode.createintern('fpc_finalize',
         result:=ccallnode.createintern('fpc_finalize',
               ccallparanode.create(
               ccallparanode.create(
-                  caddrnode.create(
+                  caddrnode.create_internal(
                       crttinode.create(
                       crttinode.create(
                           tstoreddef(p.resulttype.def),initrtti)),
                           tstoreddef(p.resulttype.def),initrtti)),
               ccallparanode.create(
               ccallparanode.create(
-                  caddrnode.create(p),
+                  caddrnode.create_internal(p),
               nil)));
               nil)));
       end;
       end;
 
 
@@ -466,9 +466,9 @@ implementation
                 end;
                 end;
               loadn:
               loadn:
                 begin
                 begin
-		  { threadvars need a helper call }
+                  { threadvars need a helper call }
                   if (tloadnode(p).symtableentry.typ=globalvarsym) and
                   if (tloadnode(p).symtableentry.typ=globalvarsym) and
-		     (vo_is_thread_var in tglobalvarsym(tloadnode(p).symtableentry).varoptions) then
+                     (vo_is_thread_var in tglobalvarsym(tloadnode(p).symtableentry).varoptions) then
                     inc(result,5)
                     inc(result,5)
                   else
                   else
                     inc(result);
                     inc(result);
@@ -530,7 +530,13 @@ end.
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.23  2004-12-02 19:26:15  peter
+  Revision 1.24  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.23  2004/12/02 19:26:15  peter
     * disable pass2inline
     * disable pass2inline
 
 
   Revision 1.22  2004/11/28 19:29:45  jonas
   Revision 1.22  2004/11/28 19:29:45  jonas

+ 14 - 8
compiler/pdecsub.pas

@@ -1821,12 +1821,12 @@ const
             { External Procedures }
             { External Procedures }
             if (po_external in pd.procoptions) then
             if (po_external in pd.procoptions) then
               begin
               begin
-	        { import by number? }
+                { import by number? }
                 if pd.import_nr<>0 then
                 if pd.import_nr<>0 then
-		  begin
-		    { Nothing to do }
-		  end
-		else
+                  begin
+                    { Nothing to do }
+                  end
+                else
                 { external name specified }
                 { external name specified }
                   if assigned(pd.import_name) then
                   if assigned(pd.import_name) then
                     begin
                     begin
@@ -1838,12 +1838,12 @@ const
                              (target_info.system in [system_i386_win32,system_i386_wdosx,
                              (target_info.system in [system_i386_win32,system_i386_wdosx,
                                                      system_i386_emx,system_i386_os2])
                                                      system_i386_emx,system_i386_os2])
                             ) then
                             ) then
-			begin    
+                        begin
                           if not(pd.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
                           if not(pd.proccalloption in [pocall_cdecl,pocall_cppdecl]) then
                             pd.setmangledname(pd.import_name^)
                             pd.setmangledname(pd.import_name^)
                           else
                           else
                             pd.setmangledname(target_info.Cprefix+pd.import_name^);
                             pd.setmangledname(target_info.Cprefix+pd.import_name^);
-			end;    
+                        end;
                     end
                     end
                 else
                 else
                   begin
                   begin
@@ -2358,7 +2358,13 @@ const
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.216  2004-12-05 00:32:56  olle
+  Revision 1.217  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.216  2004/12/05 00:32:56  olle
     + bugfix for $Z+ for mode macpas
     + bugfix for $Z+ for mode macpas
 
 
   Revision 1.215  2004/11/29 21:50:08  peter
   Revision 1.215  2004/11/29 21:50:08  peter

+ 8 - 2
compiler/pexpr.pas

@@ -321,7 +321,7 @@ implementation
              htype.setdef(tpointerdef.create(p1.resulttype));
              htype.setdef(tpointerdef.create(p1.resulttype));
              temp:=ctempcreatenode.create(htype,sizeof(aint),tt_persistent,false);
              temp:=ctempcreatenode.create(htype,sizeof(aint),tt_persistent,false);
              addstatement(newstatement,temp);
              addstatement(newstatement,temp);
-             addstatement(newstatement,cassignmentnode.create(ctemprefnode.create(temp),caddrnode.create(p1)));
+             addstatement(newstatement,cassignmentnode.create(ctemprefnode.create(temp),caddrnode.create_internal(p1)));
              addstatement(newstatement,cassignmentnode.create(
              addstatement(newstatement,cassignmentnode.create(
                  cderefnode.create(ctemprefnode.create(temp)),
                  cderefnode.create(ctemprefnode.create(temp)),
                  caddnode.create(ntyp,
                  caddnode.create(ntyp,
@@ -2505,7 +2505,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.174  2004-11-21 17:54:59  peter
+  Revision 1.175  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.174  2004/11/21 17:54:59  peter
     * ttempcreatenode.create_reg merged into .create with parameter
     * ttempcreatenode.create_reg merged into .create with parameter
       whether a register is allowed
       whether a register is allowed
     * funcret_paraloc renamed to funcretloc
     * funcret_paraloc renamed to funcretloc

+ 13 - 7
compiler/pinline.pas

@@ -327,7 +327,7 @@ implementation
             { create call to fpc_initialize }
             { create call to fpc_initialize }
             if tpointerdef(p1.resulttype.def).pointertype.def.needs_inittable then
             if tpointerdef(p1.resulttype.def).pointertype.def.needs_inittable then
              begin
              begin
-               para := ccallparanode.create(caddrnode.create(crttinode.create
+               para := ccallparanode.create(caddrnode.create_internal(crttinode.create
                           (tstoreddef(tpointerdef(p1.resulttype.def).pointertype.def),initrtti)),
                           (tstoreddef(tpointerdef(p1.resulttype.def).pointertype.def),initrtti)),
                        ccallparanode.create(ctemprefnode.create
                        ccallparanode.create(ctemprefnode.create
                           (temp),nil));
                           (temp),nil));
@@ -495,11 +495,11 @@ implementation
             ppn.left:=nil;
             ppn.left:=nil;
 
 
             { create call to fpc_dynarr_setlength }
             { create call to fpc_dynarr_setlength }
-            npara:=ccallparanode.create(caddrnode.create
+            npara:=ccallparanode.create(caddrnode.create_internal
                       (ctemprefnode.create(temp)),
                       (ctemprefnode.create(temp)),
                    ccallparanode.create(cordconstnode.create
                    ccallparanode.create(cordconstnode.create
                       (counter,s32inttype,true),
                       (counter,s32inttype,true),
-                   ccallparanode.create(caddrnode.create
+                   ccallparanode.create(caddrnode.create_internal
                       (crttinode.create(tstoreddef(destppn.resulttype.def),initrtti)),
                       (crttinode.create(tstoreddef(destppn.resulttype.def),initrtti)),
                    ccallparanode.create(ctypeconvnode.create_internal(destppn,voidpointertype),nil))));
                    ccallparanode.create(ctypeconvnode.create_internal(destppn,voidpointertype),nil))));
             addstatement(newstatement,ccallnode.createintern('fpc_dynarray_setlength',npara));
             addstatement(newstatement,ccallnode.createintern('fpc_dynarray_setlength',npara));
@@ -593,9 +593,9 @@ implementation
                      (destppn.left.resulttype.def.size,s32inttype,true),
                      (destppn.left.resulttype.def.size,s32inttype,true),
                   ccallparanode.create(ctypeconvnode.create
                   ccallparanode.create(ctypeconvnode.create
                      (ppn.left,s32inttype),
                      (ppn.left,s32inttype),
-                  ccallparanode.create(caddrnode.create
+                  ccallparanode.create(caddrnode.create_internal
                      (crttinode.create(tstoreddef(destppn.left.resulttype.def),initrtti)),
                      (crttinode.create(tstoreddef(destppn.left.resulttype.def),initrtti)),
-                  ccallparanode.create(caddrnode.create
+                  ccallparanode.create(caddrnode.create_internal
                      (destppn.left),nil))));
                      (destppn.left),nil))));
            newblock:=ccallnode.createintern('fpc_finalize_array',npara);
            newblock:=ccallnode.createintern('fpc_finalize_array',npara);
            destppn.left:=nil;
            destppn.left:=nil;
@@ -724,7 +724,7 @@ implementation
             { create call to fpc_dynarray_copy }
             { create call to fpc_dynarray_copy }
             npara:=ccallparanode.create(highppn,
             npara:=ccallparanode.create(highppn,
                    ccallparanode.create(lowppn,
                    ccallparanode.create(lowppn,
-                   ccallparanode.create(caddrnode.create
+                   ccallparanode.create(caddrnode.create_internal
                       (crttinode.create(tstoreddef(ppn.left.resulttype.def),initrtti)),
                       (crttinode.create(tstoreddef(ppn.left.resulttype.def),initrtti)),
                    ccallparanode.create
                    ccallparanode.create
                       (ctypeconvnode.create_internal(ppn.left,voidpointertype),
                       (ctypeconvnode.create_internal(ppn.left,voidpointertype),
@@ -754,7 +754,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.37  2004-11-21 17:54:59  peter
+  Revision 1.38  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.37  2004/11/21 17:54:59  peter
     * ttempcreatenode.create_reg merged into .create with parameter
     * ttempcreatenode.create_reg merged into .create with parameter
       whether a register is allowed
       whether a register is allowed
     * funcret_paraloc renamed to funcretloc
     * funcret_paraloc renamed to funcretloc

+ 8 - 2
compiler/pstatmnt.pas

@@ -489,7 +489,7 @@ implementation
                 end
                 end
                else
                else
                 begin
                 begin
-                  hp:=caddrnode.create(p);
+                  hp:=caddrnode.create_internal(p);
                   refp:=cderefnode.create(ctemprefnode.create(loadp));
                   refp:=cderefnode.create(ctemprefnode.create(loadp));
                 end;
                 end;
                addstatement(newstatement,loadp);
                addstatement(newstatement,loadp);
@@ -1147,7 +1147,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.146  2004-11-30 18:13:39  jonas
+  Revision 1.147  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.146  2004/11/30 18:13:39  jonas
     * patch from Peter to fix inlining of case statements
     * patch from Peter to fix inlining of case statements
 
 
   Revision 1.145  2004/11/21 17:54:59  peter
   Revision 1.145  2004/11/21 17:54:59  peter

+ 20 - 17
compiler/psub.pas

@@ -928,11 +928,9 @@ implementation
          if assigned(code) then
          if assigned(code) then
           begin
           begin
             { the inline procedure has already got a copy of the tree
             { the inline procedure has already got a copy of the tree
-              stored in current_procinfo.procdef.code }
+              stored in procdef.inlininginfo }
             code.free;
             code.free;
             code:=nil;
             code:=nil;
-            if (procdef.proccalloption<>pocall_inline) then
-              procdef.inlininginfo^.code:=nil;
           end;
           end;
        end;
        end;
 
 
@@ -943,8 +941,7 @@ implementation
         currpara : tparavarsym;
         currpara : tparavarsym;
       begin
       begin
         result := false;
         result := false;
-        if not assigned(procdef.inlininginfo^.code) or
-           (po_assembler in procdef.procoptions) then
+        if (po_assembler in procdef.procoptions) then
           exit;
           exit;
         for i:=0 to procdef.paras.count-1 do
         for i:=0 to procdef.paras.count-1 do
           begin
           begin
@@ -1039,19 +1036,19 @@ implementation
                end;
                end;
            end;
            end;
 
 
-         { store a copy of the original tree for inline, for
-           normal procedures only store a reference to the
-           current tree }
          if (procdef.proccalloption=pocall_inline) then
          if (procdef.proccalloption=pocall_inline) then
            begin
            begin
-             procdef.inlininginfo^.code:=code.getcopy;
-             procdef.inlininginfo^.flags:=current_procinfo.flags;
-             procdef.inlininginfo^.inlinenode:=checknodeinlining(procdef);
-             if procdef.inlininginfo^.code.nodetype=blockn then
-               include(procdef.inlininginfo^.code.flags,nf_block_with_exit);
-           end
-         else
-           procdef.inlininginfo^.code:=code;
+             { Can we inline this procedure? }
+             if checknodeinlining(procdef) then
+               begin
+                 new(procdef.inlininginfo);
+                 include(procdef.procoptions,po_has_inlininginfo);
+                 procdef.inlininginfo^.code:=code.getcopy;
+                 procdef.inlininginfo^.flags:=current_procinfo.flags;
+                 if procdef.inlininginfo^.code.nodetype=blockn then
+                   include(procdef.inlininginfo^.code.flags,nf_block_with_exit);
+               end;
+           end;
 
 
          { Print the node to tree.log }
          { Print the node to tree.log }
          if paraprintnodetree=1 then
          if paraprintnodetree=1 then
@@ -1430,7 +1427,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.221  2004-12-02 19:26:15  peter
+  Revision 1.222  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.221  2004/12/02 19:26:15  peter
     * disable pass2inline
     * disable pass2inline
 
 
   Revision 1.220  2004/11/29 18:50:15  peter
   Revision 1.220  2004/11/29 18:50:15  peter

+ 22 - 24
compiler/ptconst.pas

@@ -42,7 +42,7 @@ implementation
        symconst,symbase,symdef,symtable,
        symconst,symbase,symdef,symtable,
        aasmbase,aasmtai,aasmcpu,defutil,defcmp,
        aasmbase,aasmtai,aasmcpu,defutil,defcmp,
        { pass 1 }
        { pass 1 }
-       node,
+       node,htypechk,
        nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
        nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,
        { parser specific stuff }
        { parser specific stuff }
        pbase,pexpr,
        pbase,pexpr,
@@ -61,7 +61,7 @@ implementation
          Psetbytes = ^setbytes;
          Psetbytes = ^setbytes;
       var
       var
          len,base  : longint;
          len,base  : longint;
-         p,hp,hpstart : tnode;
+         p,hp      : tnode;
          i,j,l,
          i,j,l,
          varalign  : longint;
          varalign  : longint;
          offset,
          offset,
@@ -369,32 +369,17 @@ implementation
                       Message(parser_e_illegal_expression);
                       Message(parser_e_illegal_expression);
                 end
                 end
               else
               else
-                if p.nodetype=addrn then
+                if (p.nodetype=addrn) or
+                   is_procvar_load(p) then
                   begin
                   begin
-                    { support @@procvar in tp mode }
-                    if (m_tp_procvar in aktmodeswitches) and
-                       (taddrnode(p).left.nodetype=addrn) then
-                      p:=taddrnode(p).left;
                     { insert typeconv }
                     { insert typeconv }
                     inserttypeconv(p,t);
                     inserttypeconv(p,t);
-                    { if a typeconv node was inserted then check if it was an tc_equal. If
-                      true then we remove the node. If not tc_equal then we leave the typeconvn
-                      and the nodetype=loadn will always be false and generate the error (PFV) }
-                    if (p.nodetype=typeconvn) then
-                     begin
-                       if (ttypeconvnode(p).convtype=tc_equal) then
-                        hpstart:=taddrnode(ttypeconvnode(p).left).left
-                       else
-                        hpstart:=p;
-                     end
-                    else
-                     hpstart:=taddrnode(p).left;
-                    hp:=hpstart;
-                    while assigned(hp) and (hp.nodetype in [subscriptn,vecn]) do
+                    hp:=p;
+                    while assigned(hp) and (hp.nodetype in [addrn,typeconvn,subscriptn,vecn]) do
                       hp:=tunarynode(hp).left;
                       hp:=tunarynode(hp).left;
                     if (hp.nodetype=loadn) then
                     if (hp.nodetype=loadn) then
                       begin
                       begin
-                        hp:=hpstart;
+                        hp:=p;
                         offset:=0;
                         offset:=0;
                         while assigned(hp) and (hp.nodetype<>loadn) do
                         while assigned(hp) and (hp.nodetype<>loadn) do
                           begin
                           begin
@@ -423,7 +408,14 @@ implementation
                                      Message(parser_e_illegal_expression);
                                      Message(parser_e_illegal_expression);
                                  end;
                                  end;
                                subscriptn :
                                subscriptn :
-                                 inc(offset,tsubscriptnode(hp).vs.fieldoffset)
+                                 inc(offset,tsubscriptnode(hp).vs.fieldoffset);
+                               typeconvn :
+                                 begin
+                                   if not(ttypeconvnode(hp).convtype in [tc_equal,tc_proc_2_procvar]) then
+                                     Message(parser_e_illegal_expression);
+                                 end;
+                               addrn :
+                                 ;
                                else
                                else
                                  Message(parser_e_illegal_expression);
                                  Message(parser_e_illegal_expression);
                              end;
                              end;
@@ -1089,7 +1081,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.96  2004-11-09 17:26:47  peter
+  Revision 1.97  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.96  2004/11/09 17:26:47  peter
     * fixed wrong typecasts
     * fixed wrong typecasts
 
 
   Revision 1.95  2004/11/08 22:09:59  peter
   Revision 1.95  2004/11/08 22:09:59  peter

+ 9 - 2
compiler/symconst.pas

@@ -248,7 +248,8 @@ type
     po_has_mangledname,
     po_has_mangledname,
     po_has_public_name,
     po_has_public_name,
     po_forward,
     po_forward,
-    po_global
+    po_global,
+    po_has_inlininginfo
   );
   );
   tprocoptions=set of tprocoption;
   tprocoptions=set of tprocoption;
 
 
@@ -428,7 +429,13 @@ initialization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.95  2004-11-19 08:17:02  michael
+  Revision 1.96  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.95  2004/11/19 08:17:02  michael
   * Split po_public into po_public and po_global (Peter)
   * Split po_public into po_public and po_global (Peter)
 
 
   Revision 1.94  2004/11/17 22:21:35  peter
   Revision 1.94  2004/11/17 22:21:35  peter

+ 27 - 27
compiler/symdef.pas

@@ -494,10 +494,9 @@ interface
        end;
        end;
 
 
        tinlininginfo = record
        tinlininginfo = record
-         { node tree }
-          code : tnode;
+          { node tree }
+          code  : tnode;
           flags : tprocinfoflags;
           flags : tprocinfoflags;
-          inlinenode : boolean;
        end;
        end;
        pinlininginfo = ^tinlininginfo;
        pinlininginfo = ^tinlininginfo;
 
 
@@ -3605,8 +3604,7 @@ implementation
          import_dll:=nil;
          import_dll:=nil;
          import_name:=nil;
          import_name:=nil;
          import_nr:=0;
          import_nr:=0;
-         new(inlininginfo);
-         fillchar(inlininginfo^,sizeof(tinlininginfo),0);
+         inlininginfo:=nil;
 {$ifdef GDB}
 {$ifdef GDB}
          isstabwritten := false;
          isstabwritten := false;
 {$endif GDB}
 {$endif GDB}
@@ -3639,22 +3637,24 @@ implementation
          import_name:=nil;
          import_name:=nil;
          import_nr:=0;
          import_nr:=0;
          { inline stuff }
          { inline stuff }
-         if proccalloption=pocall_inline then
+         if (po_has_inlininginfo in procoptions) then
            begin
            begin
              ppufile.getderef(funcretsymderef);
              ppufile.getderef(funcretsymderef);
              new(inlininginfo);
              new(inlininginfo);
              ppufile.getsmallset(inlininginfo^.flags);
              ppufile.getsmallset(inlininginfo^.flags);
-             inlininginfo^.inlinenode:=boolean(ppufile.getbyte);
            end
            end
          else
          else
-           funcretsym:=nil;
+           begin
+             inlininginfo:=nil;
+             funcretsym:=nil;
+           end;
          { load para symtable }
          { load para symtable }
          parast:=tparasymtable.create(level);
          parast:=tparasymtable.create(level);
          tparasymtable(parast).ppuload(ppufile);
          tparasymtable(parast).ppuload(ppufile);
          parast.defowner:=self;
          parast.defowner:=self;
          { load local symtable }
          { load local symtable }
-         if ((proccalloption=pocall_inline) or
-             ((current_module.flags and uf_local_browser)<>0)) then
+         if (po_has_inlininginfo in procoptions) or
+            ((current_module.flags and uf_local_browser)<>0) then
           begin
           begin
             localst:=tlocalsymtable.create(level);
             localst:=tlocalsymtable.create(level);
             tlocalsymtable(localst).ppuload(ppufile);
             tlocalsymtable(localst).ppuload(ppufile);
@@ -3663,10 +3663,8 @@ implementation
          else
          else
           localst:=nil;
           localst:=nil;
          { inline stuff }
          { inline stuff }
-         if proccalloption=pocall_inline then
-           inlininginfo^.code:=ppuloadnodetree(ppufile)
-         else
-           inlininginfo := nil;
+         if (po_has_inlininginfo in procoptions) then
+           inlininginfo^.code:=ppuloadnodetree(ppufile);
          { default values for no persistent data }
          { default values for no persistent data }
          if (cs_link_deffile in aktglobalswitches) and
          if (cs_link_deffile in aktglobalswitches) and
             (tf_need_export in target_info.flags) and
             (tf_need_export in target_info.flags) and
@@ -3704,7 +3702,7 @@ implementation
             memproclocalst.start;
             memproclocalst.start;
 {$endif MEMDEBUG}
 {$endif MEMDEBUG}
           end;
           end;
-         if (proccalloption=pocall_inline) and assigned(inlininginfo) then
+         if assigned(inlininginfo) then
           begin
           begin
 {$ifdef MEMDEBUG}
 {$ifdef MEMDEBUG}
             memprocnodetree.start;
             memprocnodetree.start;
@@ -3713,11 +3711,10 @@ implementation
 {$ifdef MEMDEBUG}
 {$ifdef MEMDEBUG}
             memprocnodetree.start;
             memprocnodetree.start;
 {$endif MEMDEBUG}
 {$endif MEMDEBUG}
+            dispose(inlininginfo);
           end;
           end;
          stringdispose(import_dll);
          stringdispose(import_dll);
          stringdispose(import_name);
          stringdispose(import_name);
-         if assigned(inlininginfo) then
-           dispose(inlininginfo);
          if (po_msgstr in procoptions) then
          if (po_msgstr in procoptions) then
            strdispose(messageinf.str);
            strdispose(messageinf.str);
          if assigned(_mangledname) then
          if assigned(_mangledname) then
@@ -3768,13 +3765,11 @@ implementation
          { inline stuff }
          { inline stuff }
          oldintfcrc:=ppufile.do_crc;
          oldintfcrc:=ppufile.do_crc;
          ppufile.do_crc:=false;
          ppufile.do_crc:=false;
-         if proccalloption=pocall_inline then
+         if (po_has_inlininginfo in procoptions) then
            begin
            begin
              ppufile.putderef(funcretsymderef);
              ppufile.putderef(funcretsymderef);
              ppufile.putsmallset(inlininginfo^.flags);
              ppufile.putsmallset(inlininginfo^.flags);
-             ppufile.putbyte(byte(inlininginfo^.inlinenode));
            end;
            end;
-
          ppufile.do_crc:=oldintfcrc;
          ppufile.do_crc:=oldintfcrc;
 
 
          { write this entry }
          { write this entry }
@@ -3785,7 +3780,7 @@ implementation
 
 
          { save localsymtable for inline procedures or when local
          { save localsymtable for inline procedures or when local
            browser info is requested, this has no influence on the crc }
            browser info is requested, this has no influence on the crc }
-         if (proccalloption=pocall_inline) or
+         if (po_has_inlininginfo in procoptions) or
             ((current_module.flags and uf_local_browser)<>0) then
             ((current_module.flags and uf_local_browser)<>0) then
           begin
           begin
             { we must write a localsymtable }
             { we must write a localsymtable }
@@ -3800,9 +3795,8 @@ implementation
          { node tree for inlining }
          { node tree for inlining }
          oldintfcrc:=ppufile.do_crc;
          oldintfcrc:=ppufile.do_crc;
          ppufile.do_crc:=false;
          ppufile.do_crc:=false;
-         if proccalloption=pocall_inline then
+         if (po_has_inlininginfo in procoptions) then
            ppuwritenodetree(ppufile,inlininginfo^.code);
            ppuwritenodetree(ppufile,inlininginfo^.code);
-
          ppufile.do_crc:=oldintfcrc;
          ppufile.do_crc:=oldintfcrc;
 
 
          aktparasymtable:=oldparasymtable;
          aktparasymtable:=oldparasymtable;
@@ -4155,7 +4149,7 @@ implementation
 
 
          { Locals }
          { Locals }
          if assigned(localst) and
          if assigned(localst) and
-            ((proccalloption=pocall_inline) or
+            ((po_has_inlininginfo in procoptions) or
              ((current_module.flags and uf_local_browser)<>0)) then
              ((current_module.flags and uf_local_browser)<>0)) then
            begin
            begin
              tlocalsymtable(localst).buildderef;
              tlocalsymtable(localst).buildderef;
@@ -4163,7 +4157,7 @@ implementation
            end;
            end;
 
 
          { inline tree }
          { inline tree }
-         if (proccalloption=pocall_inline) then
+         if (po_has_inlininginfo in procoptions) then
            begin
            begin
              funcretsymderef.build(funcretsym);
              funcretsymderef.build(funcretsym);
              inlininginfo^.code.buildderefimpl;
              inlininginfo^.code.buildderefimpl;
@@ -4221,7 +4215,7 @@ implementation
           end;
           end;
 
 
         { Inline }
         { Inline }
-        if (proccalloption=pocall_inline) then
+        if (po_has_inlininginfo in procoptions) then
           begin
           begin
             inlininginfo^.code.derefimpl;
             inlininginfo^.code.derefimpl;
             { funcretsym, this is always located in the localst }
             { funcretsym, this is always located in the localst }
@@ -6129,7 +6123,13 @@ implementation
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.281  2004-12-03 15:57:39  peter
+  Revision 1.282  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.281  2004/12/03 15:57:39  peter
     * int64 can also be put in a register
     * int64 can also be put in a register
 
 
   Revision 1.280  2004/11/30 18:13:39  jonas
   Revision 1.280  2004/11/30 18:13:39  jonas

+ 9 - 3
compiler/systems/t_win32.pas

@@ -244,9 +244,9 @@ implementation
     procedure timportlibwin32.generatesmartlib;
     procedure timportlibwin32.generatesmartlib;
       var
       var
          hp1 : timportlist;
          hp1 : timportlist;
+         mangledstring : string;
 {$ifdef GDB}
 {$ifdef GDB}
          importname : string;
          importname : string;
-         mangledstring : string;
          suffix : integer;
          suffix : integer;
 {$endif GDB}
 {$endif GDB}
          hp2 : twin32imported_item;
          hp2 : twin32imported_item;
@@ -395,9 +395,9 @@ implementation
          hp1 : timportlist;
          hp1 : timportlist;
          hp2 : twin32imported_item;
          hp2 : twin32imported_item;
          l1,l2,l3,l4 : tasmlabel;
          l1,l2,l3,l4 : tasmlabel;
+         mangledstring : string;
 {$ifdef GDB}
 {$ifdef GDB}
          importname : string;
          importname : string;
-         mangledstring : string;
          suffix : integer;
          suffix : integer;
 {$endif GDB}
 {$endif GDB}
          href : treference;
          href : treference;
@@ -1623,7 +1623,13 @@ initialization
 end.
 end.
 {
 {
   $Log$
   $Log$
-  Revision 1.45  2004-11-18 10:06:19  michael
+  Revision 1.46  2004-12-05 12:28:11  peter
+    * procvar handling for tp procvar mode fixed
+    * proc to procvar moved from addrnode to typeconvnode
+    * inlininginfo is now allocated only for inline routines that
+      can be inlined, introduced a new flag po_has_inlining_info
+
+  Revision 1.45  2004/11/18 10:06:19  michael
   + Fix for win32 cycle
   + Fix for win32 cycle
 
 
   Revision 1.44  2004/11/17 22:22:12  peter
   Revision 1.44  2004/11/17 22:22:12  peter