瀏覽代碼

* add pinline unit that inserts compiler supported functions using
one or more statements
* moved finalize and setlength from ninl to pinline

peter 23 年之前
父節點
當前提交
67ede1276b
共有 11 個文件被更改,包括 685 次插入554 次删除
  1. 7 125
      compiler/i386/n386inl.pas
  2. 8 3
      compiler/nadd.pas
  3. 16 1
      compiler/nbas.pas
  4. 7 1
      compiler/ncgbas.pas
  5. 21 9
      compiler/ncnv.pas
  6. 12 81
      compiler/ninl.pas
  7. 11 7
      compiler/nld.pas
  8. 13 321
      compiler/pexpr.pas
  9. 573 0
      compiler/pinline.pas
  10. 10 4
      compiler/ptconst.pas
  11. 7 2
      compiler/symdef.pas

+ 7 - 125
compiler/i386/n386inl.pas

@@ -59,16 +59,11 @@ implementation
          addsubop:array[in_inc_x..in_dec_x] of TOpCG=(OP_ADD,OP_SUB);
        var
          asmop : tasmop;
-         pushed : tpushedsaved;
          {inc/dec}
          addconstant : boolean;
          addvalue : longint;
-         hp : tnode;
-
-      var
-         href,href2 : treference;
+         href : treference;
          hp2 : tstringconstnode;
-         dummycoll  : tparaitem;
          l : longint;
          ispushed : boolean;
          hregisterhi,
@@ -76,7 +71,6 @@ implementation
          lengthlab,
          otlabel,oflabel{,l1}   : tasmlabel;
          oldpushedparasize : longint;
-         def : tdef;
          cgop : TOpCG;
          cgsize : TCGSize;
       begin
@@ -276,36 +270,6 @@ implementation
                   emit_ref_reg(A_LEA,S_L,href,location.register);
                end;
 
-             in_finalize_x:
-               begin
-                  rg.saveusedregisters(exprasmlist,pushed,all_registers);
-                  { if a count is passed, push size, typeinfo and count }
-                  if assigned(tcallparanode(left).right) then
-                    begin
-                       secondpass(tcallparanode(tcallparanode(left).right).left);
-                       push_int(tcallparanode(left).left.resulttype.def.size);
-                       if codegenerror then
-                        exit;
-                       cg.a_param_loc(exprasmlist,tcallparanode(tcallparanode(left).right).left.location,1);
-                    end;
-
-                  { generate a reference }
-                  reference_reset_symbol(href,tstoreddef(ttypenode(tcallparanode(left).left).resulttype.def).get_rtti_label(initrtti),0);
-                  emitpushreferenceaddr(href);
-
-                  { data to finalize }
-                  secondpass(tcallparanode(left).left);
-                  if codegenerror then
-                    exit;
-                  emitpushreferenceaddr(tcallparanode(left).left.location.reference);
-                  rg.saveregvars(exprasmlist,all_registers);
-                  if assigned(tcallparanode(left).right) then
-                    emitcall('FPC_FINALIZEARRAY')
-                  else
-                    emitcall('FPC_FINALIZE');
-                  rg.restoreusedregisters(exprasmlist,pushed);
-               end;
-
             in_assigned_x :
               begin
                  secondpass(tcallparanode(left).left);
@@ -323,93 +287,6 @@ implementation
                  location_reset(location,LOC_FLAGS,OS_NO);
                  location.resflags:=F_NE;
               end;
-            in_setlength_x:
-               begin
-                  rg.saveusedregisters(exprasmlist,pushed,all_registers);
-                  l:=0;
-                  { push dimensions }
-                  hp:=left;
-                  while assigned(tcallparanode(hp).right) do
-                    begin
-                       inc(l);
-                       hp:=tcallparanode(hp).right;
-                    end;
-                  def:=tcallparanode(hp).left.resulttype.def;
-                  hp:=left;
-                  if is_dynamic_array(def) then
-                    begin
-                       { get temp. space }
-                       tg.gettempofsizereference(exprasmlist,l*4,href);
-                       { keep data start }
-                       href2:=href;
-                       { copy dimensions }
-                       hp:=left;
-                       while assigned(tcallparanode(hp).right) do
-                         begin
-                            secondpass(tcallparanode(hp).left);
-                            location_release(exprasmlist,tcallparanode(hp).left.location);
-                            cg.a_load_loc_ref(exprasmlist,tcallparanode(hp).left.location,href);
-                            inc(href.offset,4);
-                            hp:=tcallparanode(hp).right;
-                         end;
-                    end
-                  else
-                    begin
-                       secondpass(tcallparanode(hp).left);
-                       cg.a_param_loc(exprasmlist,tcallparanode(hp).left.location,1);
-                       hp:=tcallparanode(hp).right;
-                    end;
-                  { handle shortstrings separately since the hightree must be }
-                  { pushed too (JM)                                           }
-                  if not(is_dynamic_array(def)) and
-                     (tstringdef(def).string_typ = st_shortstring) then
-                    begin
-                      dummycoll:=TParaItem.Create;
-                      dummycoll.paratyp:=vs_var;
-                      dummycoll.paratype:=openshortstringtype;
-                      tcallparanode(hp).secondcallparan(dummycoll,false,false,false,0,0);
-                      dummycoll.free;
-                      if codegenerror then
-                        exit;
-                    end
-                  else secondpass(tcallparanode(hp).left);
-                  if is_dynamic_array(def) then
-                    begin
-                       emitpushreferenceaddr(href2);
-                       push_int(l);
-                       reference_reset_symbol(href2,tstoreddef(def).get_rtti_label(initrtti),0);
-                       emitpushreferenceaddr(href2);
-                       emitpushreferenceaddr(tcallparanode(hp).left.location.reference);
-                       rg.saveregvars(exprasmlist,all_registers);
-                       emitcall('FPC_DYNARR_SETLENGTH');
-                       tg.ungetiftemp(exprasmlist,href);
-                    end
-                  else
-                    { must be string }
-                    begin
-                       case tstringdef(def).string_typ of
-                          st_widestring:
-                            begin
-                              emitpushreferenceaddr(tcallparanode(hp).left.location.reference);
-                              rg.saveregvars(exprasmlist,all_registers);
-                              emitcall('FPC_WIDESTR_SETLENGTH');
-                            end;
-                          st_ansistring:
-                            begin
-                              emitpushreferenceaddr(tcallparanode(hp).left.location.reference);
-                              rg.saveregvars(exprasmlist,all_registers);
-                              emitcall('FPC_ANSISTR_SETLENGTH');
-                            end;
-                          st_shortstring:
-                            begin
-                              rg.saveregvars(exprasmlist,all_registers);
-                              emitcall('FPC_SHORTSTR_SETLENGTH');
-                            end;
-                       end;
-                    end;
-                  rg.restoreusedregisters(exprasmlist,pushed);
-                  maybe_loadself;
-               end;
             in_include_x_y,
             in_exclude_x_y:
               begin
@@ -591,7 +468,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.38  2002-04-21 15:35:54  carl
+  Revision 1.39  2002-04-23 19:16:35  peter
+    * add pinline unit that inserts compiler supported functions using
+      one or more statements
+    * moved finalize and setlength from ninl to pinline
+
+  Revision 1.38  2002/04/21 15:35:54  carl
   * changeregsize -> rg.makeregsize
 
   Revision 1.37  2002/04/19 15:39:35  peter

+ 8 - 3
compiler/nadd.pas

@@ -1052,7 +1052,7 @@ implementation
 
               { create the call to the concat routine both strings as arguments }
               result := ccallnode.createintern('fpc_'+
-                lower(tstringdef(resulttype.def).stringtypname)+'_concat',
+                tstringdef(resulttype.def).stringtypname+'_concat',
                 ccallparanode.create(right,ccallparanode.create(left,nil)));
               { we reused the arguments }
               left := nil;
@@ -1097,7 +1097,7 @@ implementation
                 end;
               { no string constant -> call compare routine }
               result := ccallnode.createintern('fpc_'+
-                lower(tstringdef(left.resulttype.def).stringtypname)+'_compare',
+                tstringdef(left.resulttype.def).stringtypname+'_compare',
                 ccallparanode.create(right,ccallparanode.create(left,nil)));
               { and compare its result with 0 according to the original operator }
               result := caddnode.create(nodetype,result,
@@ -1601,7 +1601,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.45  2002-04-04 19:05:56  peter
+  Revision 1.46  2002-04-23 19:16:34  peter
+    * add pinline unit that inserts compiler supported functions using
+      one or more statements
+    * moved finalize and setlength from ninl to pinline
+
+  Revision 1.45  2002/04/04 19:05:56  peter
     * removed unused units
     * use tlocation.size in cg.a_*loc*() routines
 

+ 16 - 1
compiler/nbas.pas

@@ -109,12 +109,14 @@ interface
         { a node which is a reference to a certain temp }
         ttemprefnode = class(tnode)
           constructor create(const temp: ttempcreatenode); virtual;
+          constructor create_offset(const temp: ttempcreatenode;aoffset:longint);
           function getcopy: tnode; override;
           function pass_1 : tnode; override;
           function det_resulttype : tnode; override;
           function docompare(p: tnode): boolean; override;
          protected
           tempinfo: ptempinfo;
+          offset : longint;
         end;
        ttemprefnodeclass = class of ttemprefnode;
 
@@ -543,6 +545,13 @@ implementation
       begin
         inherited create(temprefn);
         tempinfo := temp.tempinfo;
+        offset:=0;
+      end;
+
+    constructor ttemprefnode.create_offset(const temp: ttempcreatenode;aoffset:longint);
+      begin
+        self.create(temp);
+        offset := aoffset;
       end;
 
     function ttemprefnode.getcopy: tnode;
@@ -570,6 +579,7 @@ implementation
 
     function ttemprefnode.pass_1 : tnode;
       begin
+        location.loc:=LOC_REFERENCE;
         result := nil;
       end;
 
@@ -665,7 +675,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.21  2002-04-21 19:02:03  peter
+  Revision 1.22  2002-04-23 19:16:34  peter
+    * add pinline unit that inserts compiler supported functions using
+      one or more statements
+    * moved finalize and setlength from ninl to pinline
+
+  Revision 1.21  2002/04/21 19:02:03  peter
     * removed newn and disposen nodes, the code is now directly
       inlined from pexpr
     * -an option that will write the secondpass nodes to the .s file, this

+ 7 - 1
compiler/ncgbas.pas

@@ -263,6 +263,7 @@ interface
         { set the temp's location }
         location_reset(location,LOC_REFERENCE,def_cgsize(tempinfo^.restype.def));
         location.reference := tempinfo^.ref;
+        inc(location.reference.offset,offset);
       end;
 
 {*****************************************************************************
@@ -289,7 +290,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.13  2002-04-21 19:02:03  peter
+  Revision 1.14  2002-04-23 19:16:34  peter
+    * add pinline unit that inserts compiler supported functions using
+      one or more statements
+    * moved finalize and setlength from ninl to pinline
+
+  Revision 1.13  2002/04/21 19:02:03  peter
     * removed newn and disposen nodes, the code is now directly
       inlined from pexpr
     * -an option that will write the secondpass nodes to the .s file, this

+ 21 - 9
compiler/ncnv.pas

@@ -36,6 +36,7 @@ interface
           totype   : ttype;
           convtype : tconverttype;
           constructor create(node : tnode;const t : ttype);virtual;
+          constructor create_explicit(node : tnode;const t : ttype);
           function getcopy : tnode;override;
           function pass_1 : tnode;override;
           function det_resulttype:tnode;override;
@@ -410,6 +411,14 @@ implementation
       end;
 
 
+    constructor ttypeconvnode.create_explicit(node : tnode;const t:ttype);
+
+      begin
+         self.create(node,t);
+         toggleflag(nf_explizit);
+      end;
+
+
     function ttypeconvnode.getcopy : tnode;
 
       var
@@ -458,7 +467,7 @@ implementation
 
       begin
         result := ccallnode.createinternres(
-          'fpc_chararray_to_'+lower(tstringdef(resulttype.def).stringtypname),
+          'fpc_chararray_to_'+tstringdef(resulttype.def).stringtypname,
           ccallparanode.create(left,nil),resulttype);
         left := nil;
       end;
@@ -485,7 +494,7 @@ implementation
              exit;
            end;
         result := ccallnode.createinternres(
-          'fpc_'+lower(tstringdef(left.resulttype.def).stringtypname)+
+          'fpc_'+tstringdef(left.resulttype.def).stringtypname+
           '_to_chararray',ccallparanode.create(left,ccallparanode.create(
           cordconstnode.create(arrsize,s32bittype),nil)),resulttype);
         left := nil;
@@ -532,9 +541,8 @@ implementation
          else
            begin
              { get the correct procedure name }
-             procname := 'fpc_'+
-               lower(tstringdef(left.resulttype.def).stringtypname+
-               '_to_'+tstringdef(resulttype.def).stringtypname);
+             procname := 'fpc_'+tstringdef(left.resulttype.def).stringtypname+
+                         '_to_'+tstringdef(resulttype.def).stringtypname;
 
              { create parameter (and remove left node from typeconvnode }
              { since it's reused as parameter)                          }
@@ -585,8 +593,7 @@ implementation
                left := nil;
 
                { and the procname }
-               procname := 'fpc_char_to_' +
-                 lower(tstringdef(resulttype.def).stringtypname);
+               procname := 'fpc_char_to_' +tstringdef(resulttype.def).stringtypname;
 
                { and finally the call }
                result := ccallnode.createinternres(procname,para,resulttype);
@@ -734,7 +741,7 @@ implementation
 
       begin
         result := ccallnode.createinternres(
-          'fpc_pchar_to_'+lower(tstringdef(resulttype.def).stringtypname),
+          'fpc_pchar_to_'+tstringdef(resulttype.def).stringtypname,
           ccallparanode.create(left,nil),resulttype);
         left := nil;
       end;
@@ -1705,7 +1712,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.52  2002-04-21 19:02:03  peter
+  Revision 1.53  2002-04-23 19:16:34  peter
+    * add pinline unit that inserts compiler supported functions using
+      one or more statements
+    * moved finalize and setlength from ninl to pinline
+
+  Revision 1.52  2002/04/21 19:02:03  peter
     * removed newn and disposen nodes, the code is now directly
       inlined from pexpr
     * -an option that will write the secondpass nodes to the .s file, this

+ 12 - 81
compiler/ninl.pas

@@ -201,7 +201,7 @@ implementation
         left := nil;
 
         { create procedure name }
-        procname := 'fpc_' + lower(tstringdef(dest.resulttype.def).stringtypname)+'_';
+        procname := 'fpc_' + tstringdef(dest.resulttype.def).stringtypname+'_';
         if is_real then
           procname := procname + 'float'
         else
@@ -543,7 +543,7 @@ implementation
                 case para.left.resulttype.def.deftype of
                   stringdef :
                     begin
-                      name := procprefix+lower(tstringdef(para.left.resulttype.def).stringtypname);
+                      name := procprefix+tstringdef(para.left.resulttype.def).stringtypname;
                     end;
                   pointerdef :
                     begin
@@ -941,7 +941,7 @@ implementation
         { play a trick to have tcallnode handle invalid source parameters: }
         { the shortstring-longint val routine by default                   }
         if (sourcepara.resulttype.def.deftype = stringdef) then
-          procname := procname + lower(tstringdef(sourcepara.resulttype.def).stringtypname)
+          procname := procname + tstringdef(sourcepara.resulttype.def).stringtypname
         else procname := procname + 'shortstr';
 
         { set up the correct parameters for the call: the code para... }
@@ -1070,14 +1070,10 @@ implementation
         end;
 
       var
-         counter   : longint;
-         ppn       : tcallparanode;
-         dummycoll : tparaitem;
          vl,vl2    : longint;
          vr        : bestreal;
          hp        : tnode;
          srsym     : tsym;
-         def       : tdef;
          isreal    : boolean;
       label
          myexit;
@@ -1573,81 +1569,11 @@ implementation
                     end;
                 end;
 
+              in_finalize_x,
               in_setlength_x:
                 begin
-                   resulttype:=voidtype;
-                   if assigned(left) then
-                     begin
-                        ppn:=tcallparanode(left);
-                        counter:=0;
-                        { check type }
-                        while assigned(ppn.right) do
-                          begin
-                             set_varstate(ppn.left,true);
-                             inserttypeconv(ppn.left,s32bittype);
-                             inc(counter);
-                             ppn:=tcallparanode(ppn.right);
-                          end;
-                        { last param must be var }
-                        valid_for_var(ppn.left);
-                        set_varstate(ppn.left,false);
-                        { first param must be a string or dynamic array ...}
-                        if not((ppn.left.resulttype.def.deftype=stringdef) or
-                           (is_dynamic_array(ppn.left.resulttype.def))) then
-                          CGMessage(type_e_mismatch);
-
-                        { only dynamic arrays accept more dimensions }
-                        if (counter>1) then
-                          if (not(is_dynamic_array(ppn.left.resulttype.def))) then
-                            CGMessage(type_e_mismatch)
-                          else
-                            { check if the amount of dimensions is valid }
-                            begin
-                              def := tarraydef(ppn.left.resulttype.def).elementtype.def;
-                              while counter > 1 do
-                                begin
-                                  if not(is_dynamic_array(def)) then
-                                    begin
-                                      CGMessage(parser_e_wrong_parameter_size);
-                                      break;
-                                    end;
-                                  dec(counter);
-                                  def := tarraydef(def).elementtype.def;
-                                end;
-                            end;
-
-                       { convert shortstrings to openstring parameters }
-                       { (generate the hightree) (JM)                  }
-                       if (ppn.left.resulttype.def.deftype = stringdef) and
-                          (tstringdef(ppn.left.resulttype.def).string_typ =
-                            st_shortstring) then
-                         begin
-                           dummycoll:=tparaitem.create;
-                           dummycoll.paratyp:=vs_var;
-                           dummycoll.paratype:=openshortstringtype;
-                           tcallparanode(ppn).insert_typeconv(dummycoll,false);
-                           dummycoll.destroy;
-                         end;
-                     end
-                   else
-                     CGMessage(type_e_mismatch);
-                end;
-
-              in_finalize_x:
-                begin
-                   resulttype:=voidtype;
-                   if assigned(left) and assigned(tcallparanode(left).left) then
-                     begin
-                        { first param must be var }
-                        valid_for_var(tcallparanode(left).left);
-                        set_varstate(tcallparanode(left).left,true);
-
-                        { two parameters?, the last parameter must be a longint }
-                        if assigned(tcallparanode(left).right) then
-                         inserttypeconv(tcallparanode(tcallparanode(left).right).left,s32bittype);
-                     end
-                   else
-                     CGMessage(type_e_mismatch);
+                  { inlined from pinline }
+                  internalerror(200204231);
                 end;
 
               in_inc_x,
@@ -2341,7 +2267,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.71  2002-04-02 17:11:29  peter
+  Revision 1.72  2002-04-23 19:16:34  peter
+    * add pinline unit that inserts compiler supported functions using
+      one or more statements
+    * moved finalize and setlength from ninl to pinline
+
+  Revision 1.71  2002/04/02 17:11:29  peter
     * tlocation,treference update
     * LOC_CONSTANT added for better constant handling
     * secondadd splitted in multiple routines

+ 11 - 7
compiler/nld.pas

@@ -421,7 +421,7 @@ implementation
 
     function tassignmentnode.det_resulttype:tnode;
       var
-        hp,hp2 : tnode;
+        hp : tnode;
       begin
         result:=nil;
         resulttype:=voidtype;
@@ -450,12 +450,11 @@ implementation
         if is_dynamic_array(left.resulttype.def) and
            (right.nodetype=niln) then
          begin
-           hp := ctypeconvnode.create(left,voidpointertype);
-           hp.toggleflag(nf_explizit);
-           hp2 := crttinode.create(tstoreddef(left.resulttype.def),initrtti);
-           hp := ccallparanode.create(hp2,ccallparanode.create(hp,nil));
-           left:=nil;
+           hp:=ccallparanode.create(caddrnode.create
+                   (crttinode.create(tstoreddef(left.resulttype.def),initrtti)),
+               ccallparanode.create(ctypeconvnode.create_explicit(left,voidpointertype),nil));
            result := ccallnode.createintern('fpc_dynarray_clear',hp);
+           left:=nil;
            exit;
          end;
 
@@ -925,7 +924,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.36  2002-04-22 16:30:06  peter
+  Revision 1.37  2002-04-23 19:16:34  peter
+    * add pinline unit that inserts compiler supported functions using
+      one or more statements
+    * moved finalize and setlength from ninl to pinline
+
+  Revision 1.36  2002/04/22 16:30:06  peter
     * fixed @methodpointer
 
   Revision 1.35  2002/04/21 19:02:04  peter

+ 13 - 321
compiler/pexpr.pas

@@ -43,6 +43,8 @@ interface
 
     procedure string_dec(var t: ttype);
 
+    function parse_paras(__colon,in_prop_paras : boolean) : tnode;
+
     { the ID token has to be consumed before calling this function }
     procedure do_member_read(getaddr : boolean;sym : tsym;var p1 : tnode;var again : boolean);
 
@@ -72,7 +74,7 @@ implementation
        nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,nbas,
        { parser }
        scanner,
-       pbase,
+       pbase,pinline,
        { codegen }
        cgbase
        ;
@@ -218,313 +220,6 @@ implementation
       end;
 
 
-    function new_dispose_statement(is_new:boolean) : tnode;
-      var
-        newstatement : tstatementnode;
-        temp         : ttempcreatenode;
-        para         : tcallparanode;
-        p,p2     : tnode;
-        again    : boolean; { dummy for do_proc_call }
-        destructorname : stringid;
-        sym      : tsym;
-        classh   : tobjectdef;
-        destructorpos,
-        storepos : tfileposinfo;
-      begin
-        consume(_LKLAMMER);
-        p:=comp_expr(true);
-        { calc return type }
-        { rg.cleartempgen; }
-        set_varstate(p,(not is_new));
-        { constructor,destructor specified }
-        if try_to_consume(_COMMA) then
-          begin
-            { extended syntax of new and dispose }
-            { function styled new is handled in factor }
-            { destructors have no parameters }
-            destructorname:=pattern;
-            destructorpos:=akttokenpos;
-            consume(_ID);
-
-            if (p.resulttype.def.deftype<>pointerdef) then
-              begin
-                 Message1(type_e_pointer_type_expected,p.resulttype.def.typename);
-                 p.free;
-                 p:=factor(false);
-                 p.free;
-                 consume(_RKLAMMER);
-                 new_dispose_statement:=cerrornode.create;
-                 exit;
-              end;
-            { first parameter must be an object or class }
-            if tpointerdef(p.resulttype.def).pointertype.def.deftype<>objectdef then
-              begin
-                 Message(parser_e_pointer_to_class_expected);
-                 p.free;
-                 new_dispose_statement:=factor(false);
-                 consume_all_until(_RKLAMMER);
-                 consume(_RKLAMMER);
-                 exit;
-              end;
-            { check, if the first parameter is a pointer to a _class_ }
-            classh:=tobjectdef(tpointerdef(p.resulttype.def).pointertype.def);
-            if is_class(classh) then
-              begin
-                 Message(parser_e_no_new_or_dispose_for_classes);
-                 new_dispose_statement:=factor(false);
-                 consume_all_until(_RKLAMMER);
-                 consume(_RKLAMMER);
-                 exit;
-              end;
-            { search cons-/destructor, also in parent classes }
-            storepos:=akttokenpos;
-            akttokenpos:=destructorpos;
-            sym:=search_class_member(classh,destructorname);
-            akttokenpos:=storepos;
-
-            { the second parameter of new/dispose must be a call }
-            { to a cons-/destructor                              }
-            if (not assigned(sym)) or (sym.typ<>procsym) then
-              begin
-                 if is_new then
-                  Message(parser_e_expr_have_to_be_constructor_call)
-                 else
-                  Message(parser_e_expr_have_to_be_destructor_call);
-                 p.free;
-                 new_dispose_statement:=cerrornode.create;
-              end
-            else
-              begin
-                if is_new then
-                 p2:=chnewnode.create(tpointerdef(p.resulttype.def).pointertype)
-                else
-                 p2:=chdisposenode.create(p);
-                do_resulttypepass(p2);
-                if is_new then
-                  do_member_read(false,sym,p2,again)
-                else
-                  begin
-                    if not(m_fpc in aktmodeswitches) then
-                      do_member_read(false,sym,p2,again)
-                    else
-                      begin
-                        p2:=ccallnode.create(nil,tprocsym(sym),sym.owner,p2);
-                        { support dispose(p,done()); }
-                        if try_to_consume(_LKLAMMER) then
-                          begin
-                            if not try_to_consume(_RKLAMMER) then
-                              begin
-                                Message(parser_e_no_paras_for_destructor);
-                                consume_all_until(_RKLAMMER);
-                                consume(_RKLAMMER);
-                              end;
-                          end;
-                      end;
-                  end;
-
-                { we need the real called method }
-                { rg.cleartempgen;}
-                do_resulttypepass(p2);
-                if not codegenerror then
-                 begin
-                   if is_new then
-                    begin
-                      if (tcallnode(p2).procdefinition.proctypeoption<>potype_constructor) then
-                        Message(parser_e_expr_have_to_be_constructor_call);
-                      p2.resulttype:=p.resulttype;
-                      p2:=cassignmentnode.create(p,p2);
-                    end
-                   else
-                    begin
-                      if (tcallnode(p2).procdefinition.proctypeoption<>potype_destructor) then
-                        Message(parser_e_expr_have_to_be_destructor_call);
-                    end;
-                 end;
-                new_dispose_statement:=p2;
-              end;
-          end
-        else
-          begin
-             if (p.resulttype.def.deftype<>pointerdef) then
-               Begin
-                  Message1(type_e_pointer_type_expected,p.resulttype.def.typename);
-                  new_dispose_statement:=cerrornode.create;
-               end
-             else
-               begin
-                  if (tpointerdef(p.resulttype.def).pointertype.def.deftype=objectdef) and
-                     (oo_has_vmt in tobjectdef(tpointerdef(p.resulttype.def).pointertype.def).objectoptions) then
-                    Message(parser_w_use_extended_syntax_for_objects);
-                  if (tpointerdef(p.resulttype.def).pointertype.def.deftype=orddef) and
-                     (torddef(tpointerdef(p.resulttype.def).pointertype.def).typ=uvoid) then
-                    begin
-                      if (m_tp7 in aktmodeswitches) or
-                         (m_delphi in aktmodeswitches) then
-                       Message(parser_w_no_new_dispose_on_void_pointers)
-                      else
-                       Message(parser_e_no_new_dispose_on_void_pointers);
-                    end;
-
-                  { create statements with call to getmem+initialize or
-                    finalize+freemem }
-                  new_dispose_statement:=internalstatements(newstatement);
-
-                  if is_new then
-                   begin
-                     { create temp for result }
-                     temp := ctempcreatenode.create(p.resulttype,p.resulttype.def.size,true);
-                     addstatement(newstatement,temp);
-
-                     { create call to fpc_getmem }
-                     para := ccallparanode.create(cordconstnode.create
-                         (tpointerdef(p.resulttype.def).pointertype.def.size,s32bittype),nil);
-                     addstatement(newstatement,cassignmentnode.create(
-                         ctemprefnode.create(temp),
-                         ccallnode.createintern('fpc_getmem',para)));
-
-                     { create call to fpc_initialize }
-                     if tpointerdef(p.resulttype.def).pointertype.def.needs_inittable then
-                      begin
-                        para := ccallparanode.create(caddrnode.create(crttinode.create(
-                                   tstoreddef(tpointerdef(p.resulttype.def).pointertype.def),initrtti)),
-                                ccallparanode.create(ctemprefnode.create
-                                   (temp),nil));
-                        addstatement(newstatement,ccallnode.createintern('fpc_initialize',para));
-                      end;
-
-                     { copy the temp to the destination }
-                     addstatement(newstatement,cassignmentnode.create(
-                         p,
-                         ctemprefnode.create(temp)));
-
-                     { release temp }
-                     addstatement(newstatement,ctempdeletenode.create(temp));
-                   end
-                  else
-                   begin
-                     { create call to fpc_finalize }
-                     if tpointerdef(p.resulttype.def).pointertype.def.needs_inittable then
-                      begin
-                        { we need to use a copy of p here }
-                        para := ccallparanode.create(caddrnode.create(crttinode.create
-                                   (tstoreddef(tpointerdef(p.resulttype.def).pointertype.def),initrtti)),
-                                ccallparanode.create(p.getcopy,nil));
-                        addstatement(newstatement,ccallnode.createintern('fpc_finalize',para));
-                      end;
-
-                     { create call to fpc_freemem }
-                     para := ccallparanode.create(p,nil);
-                     addstatement(newstatement,ccallnode.createintern('fpc_freemem',para));
-                   end;
-               end;
-          end;
-        consume(_RKLAMMER);
-      end;
-
-
-    function new_function : tnode;
-      var
-        newstatement : tstatementnode;
-        newblock     : tblocknode;
-        temp         : ttempcreatenode;
-        para         : tcallparanode;
-        p1,p2  : tnode;
-        classh : tobjectdef;
-        sym    : tsym;
-        again  : boolean; { dummy for do_proc_call }
-      begin
-        consume(_LKLAMMER);
-        p1:=factor(false);
-        if p1.nodetype<>typen then
-         begin
-           Message(type_e_type_id_expected);
-           p1.destroy;
-           p1:=cerrornode.create;
-           do_resulttypepass(p1);
-         end;
-
-        if (p1.resulttype.def.deftype<>pointerdef) then
-          Message1(type_e_pointer_type_expected,p1.resulttype.def.typename)
-        else
-         if token=_RKLAMMER then
-          begin
-            if (tpointerdef(p1.resulttype.def).pointertype.def.deftype=objectdef) and
-               (oo_has_vmt in tobjectdef(tpointerdef(p1.resulttype.def).pointertype.def).objectoptions)  then
-              Message(parser_w_use_extended_syntax_for_objects);
-
-            { create statements with call to getmem+initialize }
-            newblock:=internalstatements(newstatement);
-
-            { create temp for result }
-            temp := ctempcreatenode.create(p1.resulttype,p1.resulttype.def.size,true);
-            addstatement(newstatement,temp);
-
-            { create call to fpc_getmem }
-            para := ccallparanode.create(cordconstnode.create
-                (tpointerdef(p1.resulttype.def).pointertype.def.size,s32bittype),nil);
-            addstatement(newstatement,cassignmentnode.create(
-                ctemprefnode.create(temp),
-                ccallnode.createintern('fpc_getmem',para)));
-
-            { create call to fpc_initialize }
-            if tpointerdef(p1.resulttype.def).pointertype.def.needs_inittable then
-             begin
-               para := ccallparanode.create(caddrnode.create(crttinode.create
-                          (tstoreddef(tpointerdef(p1.resulttype.def).pointertype.def),initrtti)),
-                       ccallparanode.create(ctemprefnode.create
-                          (temp),nil));
-               addstatement(newstatement,ccallnode.createintern('fpc_initialize',para));
-             end;
-
-            { the last statement should return the value as
-              location and type, this is done be referencing the
-              temp and converting it first from a persistent temp to
-              normal temp }
-            addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
-            addstatement(newstatement,ctemprefnode.create(temp));
-
-            p1.destroy;
-            p1:=newblock;
-            consume(_RKLAMMER);
-          end
-        else
-          begin
-            p2:=chnewnode.create(tpointerdef(p1.resulttype.def).pointertype);
-            do_resulttypepass(p2);
-            consume(_COMMA);
-            afterassignment:=false;
-            { determines the current object defintion }
-            classh:=tobjectdef(p2.resulttype.def);
-            if classh.deftype=objectdef then
-             begin
-               { check for an abstract class }
-               if (oo_has_abstract in classh.objectoptions) then
-                Message(sym_e_no_instance_of_abstract_object);
-               { search the constructor also in the symbol tables of
-                 the parents }
-               sym:=searchsym_in_class(classh,pattern);
-               consume(_ID);
-               do_member_read(false,sym,p2,again);
-               { we need to know which procedure is called }
-               do_resulttypepass(p2);
-               if (p2.nodetype<>calln) or
-                  (assigned(tcallnode(p2).procdefinition) and
-                   (tcallnode(p2).procdefinition.proctypeoption<>potype_constructor)) then
-                Message(parser_e_expr_have_to_be_constructor_call);
-             end
-            else
-             Message(parser_e_pointer_to_class_expected);
-            { constructors return boolean, update resulttype to return
-              the pointer to the object }
-            p2.resulttype:=p1.resulttype;
-            p1.destroy;
-            p1:=p2;
-            consume(_RKLAMMER);
-          end;
-        new_function:=p1;
-      end;
-
-
      function statement_syssym(l : longint) : tnode;
       var
         p1,p2,paras  : tnode;
@@ -724,7 +419,7 @@ implementation
 
           in_finalize_x:
             begin
-              consume(_LKLAMMER);
+{              consume(_LKLAMMER);
               in_args:=true;
               p1:=comp_expr(true);
               if token=_COMMA then
@@ -737,6 +432,8 @@ implementation
               p2:=ccallparanode.create(p1,p2);
               statement_syssym:=geninlinenode(in_finalize_x,false,p2);
               consume(_RKLAMMER);
+}
+              statement_syssym:=inline_finalize;
             end;
 
           in_concat_x :
@@ -783,17 +480,7 @@ implementation
 
           in_setlength_x:
             begin
-              if token=_LKLAMMER then
-               begin
-                 consume(_LKLAMMER);
-                 in_args:=true;
-                 paras:=parse_paras(false,false);
-                 consume(_RKLAMMER);
-               end
-              else
-               paras:=nil;
-              p1:=geninlinenode(l,false,paras);
-              statement_syssym := p1;
+              statement_syssym := inline_setlength;
             end;
 
           in_length_x:
@@ -2537,7 +2224,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.63  2002-04-21 19:02:05  peter
+  Revision 1.64  2002-04-23 19:16:34  peter
+    * add pinline unit that inserts compiler supported functions using
+      one or more statements
+    * moved finalize and setlength from ninl to pinline
+
+  Revision 1.63  2002/04/21 19:02:05  peter
     * removed newn and disposen nodes, the code is now directly
       inlined from pexpr
     * -an option that will write the secondpass nodes to the .s file, this

+ 573 - 0
compiler/pinline.pas

@@ -0,0 +1,573 @@
+{
+    $Id$
+    Copyright (c) 1998-2001 by Florian Klaempfl
+
+    Generates nodes for routines that need compiler support
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+ ****************************************************************************
+}
+unit pinline;
+
+{$i defines.inc}
+
+interface
+
+    uses
+      symtype,
+      node,
+      globals,
+      cpuinfo;
+
+    function new_dispose_statement(is_new:boolean) : tnode;
+    function new_function : tnode;
+
+    function inline_setlength : tnode;
+    function inline_finalize : tnode;
+
+
+implementation
+
+    uses
+{$ifdef delphi}
+       SysUtils,
+{$endif}
+       { common }
+       cutils,
+       { global }
+       globtype,tokens,verbose,
+       systems,widestr,
+       { symtable }
+       symconst,symbase,symdef,symsym,symtable,types,
+       { pass 1 }
+       pass_1,htypechk,
+       nmat,nadd,ncal,nmem,nset,ncnv,ninl,ncon,nld,nflw,nbas,
+       { parser }
+       scanner,
+       pbase,pexpr,
+       { codegen }
+       cgbase
+       ;
+
+
+    function new_dispose_statement(is_new:boolean) : tnode;
+      var
+        newstatement : tstatementnode;
+        temp         : ttempcreatenode;
+        para         : tcallparanode;
+        p,p2     : tnode;
+        again    : boolean; { dummy for do_proc_call }
+        destructorname : stringid;
+        sym      : tsym;
+        classh   : tobjectdef;
+        destructorpos,
+        storepos : tfileposinfo;
+      begin
+        consume(_LKLAMMER);
+        p:=comp_expr(true);
+        { calc return type }
+        set_varstate(p,(not is_new));
+        { constructor,destructor specified }
+        if try_to_consume(_COMMA) then
+          begin
+            { extended syntax of new and dispose }
+            { function styled new is handled in factor }
+            { destructors have no parameters }
+            destructorname:=pattern;
+            destructorpos:=akttokenpos;
+            consume(_ID);
+
+            if (p.resulttype.def.deftype<>pointerdef) then
+              begin
+                 Message1(type_e_pointer_type_expected,p.resulttype.def.typename);
+                 p.free;
+                 p:=factor(false);
+                 p.free;
+                 consume(_RKLAMMER);
+                 new_dispose_statement:=cerrornode.create;
+                 exit;
+              end;
+            { first parameter must be an object or class }
+            if tpointerdef(p.resulttype.def).pointertype.def.deftype<>objectdef then
+              begin
+                 Message(parser_e_pointer_to_class_expected);
+                 p.free;
+                 new_dispose_statement:=factor(false);
+                 consume_all_until(_RKLAMMER);
+                 consume(_RKLAMMER);
+                 exit;
+              end;
+            { check, if the first parameter is a pointer to a _class_ }
+            classh:=tobjectdef(tpointerdef(p.resulttype.def).pointertype.def);
+            if is_class(classh) then
+              begin
+                 Message(parser_e_no_new_or_dispose_for_classes);
+                 new_dispose_statement:=factor(false);
+                 consume_all_until(_RKLAMMER);
+                 consume(_RKLAMMER);
+                 exit;
+              end;
+            { search cons-/destructor, also in parent classes }
+            storepos:=akttokenpos;
+            akttokenpos:=destructorpos;
+            sym:=search_class_member(classh,destructorname);
+            akttokenpos:=storepos;
+
+            { the second parameter of new/dispose must be a call }
+            { to a cons-/destructor                              }
+            if (not assigned(sym)) or (sym.typ<>procsym) then
+              begin
+                 if is_new then
+                  Message(parser_e_expr_have_to_be_constructor_call)
+                 else
+                  Message(parser_e_expr_have_to_be_destructor_call);
+                 p.free;
+                 new_dispose_statement:=cerrornode.create;
+              end
+            else
+              begin
+                if is_new then
+                 p2:=chnewnode.create(tpointerdef(p.resulttype.def).pointertype)
+                else
+                 p2:=chdisposenode.create(p);
+                do_resulttypepass(p2);
+                if is_new then
+                  do_member_read(false,sym,p2,again)
+                else
+                  begin
+                    if not(m_fpc in aktmodeswitches) then
+                      do_member_read(false,sym,p2,again)
+                    else
+                      begin
+                        p2:=ccallnode.create(nil,tprocsym(sym),sym.owner,p2);
+                        { support dispose(p,done()); }
+                        if try_to_consume(_LKLAMMER) then
+                          begin
+                            if not try_to_consume(_RKLAMMER) then
+                              begin
+                                Message(parser_e_no_paras_for_destructor);
+                                consume_all_until(_RKLAMMER);
+                                consume(_RKLAMMER);
+                              end;
+                          end;
+                      end;
+                  end;
+
+                { we need the real called method }
+                { rg.cleartempgen;}
+                do_resulttypepass(p2);
+                if not codegenerror then
+                 begin
+                   if is_new then
+                    begin
+                      if (tcallnode(p2).procdefinition.proctypeoption<>potype_constructor) then
+                        Message(parser_e_expr_have_to_be_constructor_call);
+                      p2.resulttype:=p.resulttype;
+                      p2:=cassignmentnode.create(p,p2);
+                    end
+                   else
+                    begin
+                      if (tcallnode(p2).procdefinition.proctypeoption<>potype_destructor) then
+                        Message(parser_e_expr_have_to_be_destructor_call);
+                    end;
+                 end;
+                new_dispose_statement:=p2;
+              end;
+          end
+        else
+          begin
+             if (p.resulttype.def.deftype<>pointerdef) then
+               Begin
+                  Message1(type_e_pointer_type_expected,p.resulttype.def.typename);
+                  new_dispose_statement:=cerrornode.create;
+               end
+             else
+               begin
+                  if (tpointerdef(p.resulttype.def).pointertype.def.deftype=objectdef) and
+                     (oo_has_vmt in tobjectdef(tpointerdef(p.resulttype.def).pointertype.def).objectoptions) then
+                    Message(parser_w_use_extended_syntax_for_objects);
+                  if (tpointerdef(p.resulttype.def).pointertype.def.deftype=orddef) and
+                     (torddef(tpointerdef(p.resulttype.def).pointertype.def).typ=uvoid) then
+                    begin
+                      if (m_tp7 in aktmodeswitches) or
+                         (m_delphi in aktmodeswitches) then
+                       Message(parser_w_no_new_dispose_on_void_pointers)
+                      else
+                       Message(parser_e_no_new_dispose_on_void_pointers);
+                    end;
+
+                  { create statements with call to getmem+initialize or
+                    finalize+freemem }
+                  new_dispose_statement:=internalstatements(newstatement);
+
+                  if is_new then
+                   begin
+                     { create temp for result }
+                     temp := ctempcreatenode.create(p.resulttype,p.resulttype.def.size,true);
+                     addstatement(newstatement,temp);
+
+                     { create call to fpc_getmem }
+                     para := ccallparanode.create(cordconstnode.create
+                         (tpointerdef(p.resulttype.def).pointertype.def.size,s32bittype),nil);
+                     addstatement(newstatement,cassignmentnode.create(
+                         ctemprefnode.create(temp),
+                         ccallnode.createintern('fpc_getmem',para)));
+
+                     { create call to fpc_initialize }
+                     if tpointerdef(p.resulttype.def).pointertype.def.needs_inittable then
+                      begin
+                        para := ccallparanode.create(caddrnode.create(crttinode.create(
+                                   tstoreddef(tpointerdef(p.resulttype.def).pointertype.def),initrtti)),
+                                ccallparanode.create(ctemprefnode.create
+                                   (temp),nil));
+                        addstatement(newstatement,ccallnode.createintern('fpc_initialize',para));
+                      end;
+
+                     { copy the temp to the destination }
+                     addstatement(newstatement,cassignmentnode.create(
+                         p,
+                         ctemprefnode.create(temp)));
+
+                     { release temp }
+                     addstatement(newstatement,ctempdeletenode.create(temp));
+                   end
+                  else
+                   begin
+                     { create call to fpc_finalize }
+                     if tpointerdef(p.resulttype.def).pointertype.def.needs_inittable then
+                      begin
+                        { we need to use a copy of p here }
+                        para := ccallparanode.create(caddrnode.create(crttinode.create
+                                   (tstoreddef(tpointerdef(p.resulttype.def).pointertype.def),initrtti)),
+                                ccallparanode.create(p.getcopy,nil));
+                        addstatement(newstatement,ccallnode.createintern('fpc_finalize',para));
+                      end;
+
+                     { create call to fpc_freemem }
+                     para := ccallparanode.create(p,nil);
+                     addstatement(newstatement,ccallnode.createintern('fpc_freemem',para));
+                   end;
+               end;
+          end;
+        consume(_RKLAMMER);
+      end;
+
+
+    function new_function : tnode;
+      var
+        newstatement : tstatementnode;
+        newblock     : tblocknode;
+        temp         : ttempcreatenode;
+        para         : tcallparanode;
+        p1,p2  : tnode;
+        classh : tobjectdef;
+        sym    : tsym;
+        again  : boolean; { dummy for do_proc_call }
+      begin
+        consume(_LKLAMMER);
+        p1:=factor(false);
+        if p1.nodetype<>typen then
+         begin
+           Message(type_e_type_id_expected);
+           p1.destroy;
+           p1:=cerrornode.create;
+           do_resulttypepass(p1);
+         end;
+
+        if (p1.resulttype.def.deftype<>pointerdef) then
+          Message1(type_e_pointer_type_expected,p1.resulttype.def.typename)
+        else
+         if token=_RKLAMMER then
+          begin
+            if (tpointerdef(p1.resulttype.def).pointertype.def.deftype=objectdef) and
+               (oo_has_vmt in tobjectdef(tpointerdef(p1.resulttype.def).pointertype.def).objectoptions)  then
+              Message(parser_w_use_extended_syntax_for_objects);
+
+            { create statements with call to getmem+initialize }
+            newblock:=internalstatements(newstatement);
+
+            { create temp for result }
+            temp := ctempcreatenode.create(p1.resulttype,p1.resulttype.def.size,true);
+            addstatement(newstatement,temp);
+
+            { create call to fpc_getmem }
+            para := ccallparanode.create(cordconstnode.create
+                (tpointerdef(p1.resulttype.def).pointertype.def.size,s32bittype),nil);
+            addstatement(newstatement,cassignmentnode.create(
+                ctemprefnode.create(temp),
+                ccallnode.createintern('fpc_getmem',para)));
+
+            { create call to fpc_initialize }
+            if tpointerdef(p1.resulttype.def).pointertype.def.needs_inittable then
+             begin
+               para := ccallparanode.create(caddrnode.create(crttinode.create
+                          (tstoreddef(tpointerdef(p1.resulttype.def).pointertype.def),initrtti)),
+                       ccallparanode.create(ctemprefnode.create
+                          (temp),nil));
+               addstatement(newstatement,ccallnode.createintern('fpc_initialize',para));
+             end;
+
+            { the last statement should return the value as
+              location and type, this is done be referencing the
+              temp and converting it first from a persistent temp to
+              normal temp }
+            addstatement(newstatement,ctempdeletenode.create_normal_temp(temp));
+            addstatement(newstatement,ctemprefnode.create(temp));
+
+            p1.destroy;
+            p1:=newblock;
+            consume(_RKLAMMER);
+          end
+        else
+          begin
+            p2:=chnewnode.create(tpointerdef(p1.resulttype.def).pointertype);
+            do_resulttypepass(p2);
+            consume(_COMMA);
+            afterassignment:=false;
+            { determines the current object defintion }
+            classh:=tobjectdef(p2.resulttype.def);
+            if classh.deftype=objectdef then
+             begin
+               { check for an abstract class }
+               if (oo_has_abstract in classh.objectoptions) then
+                Message(sym_e_no_instance_of_abstract_object);
+               { search the constructor also in the symbol tables of
+                 the parents }
+               sym:=searchsym_in_class(classh,pattern);
+               consume(_ID);
+               do_member_read(false,sym,p2,again);
+               { we need to know which procedure is called }
+               do_resulttypepass(p2);
+               if (p2.nodetype<>calln) or
+                  (assigned(tcallnode(p2).procdefinition) and
+                   (tcallnode(p2).procdefinition.proctypeoption<>potype_constructor)) then
+                Message(parser_e_expr_have_to_be_constructor_call);
+             end
+            else
+             Message(parser_e_pointer_to_class_expected);
+            { constructors return boolean, update resulttype to return
+              the pointer to the object }
+            p2.resulttype:=p1.resulttype;
+            p1.destroy;
+            p1:=p2;
+            consume(_RKLAMMER);
+          end;
+        new_function:=p1;
+      end;
+
+
+    function inline_setlength : tnode;
+      var
+        paras   : tnode;
+        npara,
+        ppn     : tcallparanode;
+        counter : integer;
+        isarray : boolean;
+        def     : tdef;
+        destppn : tnode;
+        newstatement : tstatementnode;
+        temp    : ttempcreatenode;
+        newblock : tnode;
+      begin
+        { for easy exiting if something goes wrong }
+        result := cerrornode.create;
+
+        consume(_LKLAMMER);
+        paras:=parse_paras(false,false);
+        consume(_RKLAMMER);
+        if not assigned(paras) then
+         begin
+           CGMessage(parser_e_wrong_parameter_size);
+           exit;
+         end;
+
+        counter:=0;
+        if assigned(paras) then
+         begin
+           { check type of lengths }
+           ppn:=tcallparanode(paras);
+           while assigned(ppn.right) do
+            begin
+              set_varstate(ppn.left,true);
+              inserttypeconv(ppn.left,s32bittype);
+              inc(counter);
+              ppn:=tcallparanode(ppn.right);
+            end;
+         end;
+        if counter=0 then
+         begin
+           CGMessage(parser_e_wrong_parameter_size);
+           paras.free;
+           exit;
+         end;
+        { last param must be var }
+        destppn:=ppn.left;
+        inc(parsing_para_level);
+        valid_for_var(destppn);
+        set_varstate(destppn,false);
+        dec(parsing_para_level);
+        { first param must be a string or dynamic array ...}
+        isarray:=is_dynamic_array(destppn.resulttype.def);
+        if not((destppn.resulttype.def.deftype=stringdef) or
+               isarray) then
+         begin
+           CGMessage(type_e_mismatch);
+           paras.free;
+           exit;
+         end;
+
+        { only dynamic arrays accept more dimensions }
+        if (counter>1) then
+         begin
+           if (not isarray) then
+            CGMessage(type_e_mismatch)
+           else
+            begin
+              { check if the amount of dimensions is valid }
+              def := tarraydef(destppn.resulttype.def).elementtype.def;
+              while counter > 1 do
+                begin
+                  if not(is_dynamic_array(def)) then
+                    begin
+                      CGMessage(parser_e_wrong_parameter_size);
+                      break;
+                    end;
+                  dec(counter);
+                  def := tarraydef(def).elementtype.def;
+                end;
+            end;
+         end;
+
+        if isarray then
+         begin
+            { create statements with call initialize the arguments and
+              call fpc_dynarr_setlength }
+            newblock:=internalstatements(newstatement);
+
+            { get temp for array of lengths }
+            temp := ctempcreatenode.create(s32bittype,counter*s32bittype.def.size,true);
+            addstatement(newstatement,temp);
+
+            { load array of lengths }
+            ppn:=tcallparanode(paras);
+            counter:=0;
+            while assigned(ppn.right) do
+             begin
+               addstatement(newstatement,cassignmentnode.create(
+                   ctemprefnode.create_offset(temp,counter*s32bittype.def.size),
+                   ppn.left));
+               ppn.left:=nil;
+               inc(counter);
+               ppn:=tcallparanode(ppn.right);
+             end;
+            { destppn is also reused }
+            ppn.left:=nil;
+
+            { create call to fpc_dynarr_setlength }
+            npara:=ccallparanode.create(caddrnode.create
+                      (ctemprefnode.create(temp)),
+                   ccallparanode.create(cordconstnode.create
+                      (counter,s32bittype),
+                   ccallparanode.create(caddrnode.create
+                      (crttinode.create(tstoreddef(destppn.resulttype.def),initrtti)),
+                   ccallparanode.create(ctypeconvnode.create_explicit(destppn,voidpointertype),nil))));
+            addstatement(newstatement,ccallnode.createintern('fpc_dynarray_setlength',npara));
+            addstatement(newstatement,ctempdeletenode.create(temp));
+
+            { we don't need original the callparanodes tree }
+            paras.free;
+         end
+        else
+         begin
+            { we can reuse the supplied parameters }
+            newblock:=ccallnode.createintern(
+               'fpc_'+tstringdef(destppn.resulttype.def).stringtypname+'_setlength',paras);
+         end;
+
+        result.free;
+        result:=newblock;
+      end;
+
+
+    function inline_finalize : tnode;
+      var
+        newblock,
+        paras   : tnode;
+        npara,
+        destppn,
+        ppn     : tcallparanode;
+      begin
+        { for easy exiting if something goes wrong }
+        result := cerrornode.create;
+
+        consume(_LKLAMMER);
+        paras:=parse_paras(false,false);
+        consume(_RKLAMMER);
+        if not assigned(paras) then
+         begin
+           CGMessage(parser_e_wrong_parameter_size);
+           exit;
+         end;
+
+        ppn:=tcallparanode(paras);
+        { 2 arguments? }
+        if assigned(ppn.right) then
+         begin
+           destppn:=tcallparanode(ppn.right);
+           { 3 arguments is invalid }
+           if assigned(destppn.right) then
+            begin
+              CGMessage(parser_e_wrong_parameter_size);
+              paras.free;
+              exit;
+            end;
+           { create call to fpc_finalize_array }
+           npara:=ccallparanode.create(cordconstnode.create
+                     (destppn.left.resulttype.def.size,s32bittype),
+                  ccallparanode.create(ctypeconvnode.create
+                     (ppn.left,s32bittype),
+                  ccallparanode.create(caddrnode.create
+                     (crttinode.create(tstoreddef(destppn.left.resulttype.def),initrtti)),
+                  ccallparanode.create(caddrnode.create
+                     (destppn.left),nil))));
+           newblock:=ccallnode.createintern('fpc_finalize_array',npara);
+           destppn.left:=nil;
+           ppn.left:=nil;
+         end
+        else
+         begin
+           { create call to fpc_finalize }
+           npara:=ccallparanode.create(caddrnode.create
+                     (crttinode.create(tstoreddef(ppn.left.resulttype.def),initrtti)),
+                  ccallparanode.create(caddrnode.create
+                     (ppn.left),nil));
+           newblock:=ccallnode.createintern('fpc_finalize',npara);
+           ppn.left:=nil;
+         end;
+        paras.free;
+        result.free;
+        result:=newblock;
+      end;
+
+end.
+{
+  $Log$
+  Revision 1.1  2002-04-23 19:16:35  peter
+    * add pinline unit that inserts compiler supported functions using
+      one or more statements
+    * moved finalize and setlength from ninl to pinline
+
+}

+ 10 - 4
compiler/ptconst.pas

@@ -774,15 +774,16 @@ implementation
                             Message1(sym_e_illegal_field,s);
                             error := true;
                           end;
-                        if not assigned(srsym) or
-                           (s <> srsym.name) then
+                        if (not error) and
+                           (not assigned(srsym) or
+                            (s <> srsym.name)) then
                           { possible variant record (JM) }
                           begin
                             { All parts of a variant start at the same offset      }
                             { Also allow jumping from one variant part to another, }
                             { as long as the offsets match                         }
                             if (assigned(srsym) and
-                               (tvarsym(recsym).address = tvarsym(srsym).address)) or
+                                (tvarsym(recsym).address = tvarsym(srsym).address)) or
                                { srsym is not assigned after parsing w2 in the      }
                                { typed const in the next example:                   }
                                {   type tr = record case byte of                    }
@@ -970,7 +971,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.44  2002-04-20 21:32:24  carl
+  Revision 1.45  2002-04-23 19:16:35  peter
+    * add pinline unit that inserts compiler supported functions using
+      one or more statements
+    * moved finalize and setlength from ninl to pinline
+
+  Revision 1.44  2002/04/20 21:32:24  carl
   + generic FPC_CHECKPOINTER
   + first parameter offset in stack now portable
   * rename some constants

+ 7 - 2
compiler/symdef.pas

@@ -1252,7 +1252,7 @@ implementation
     function tstringdef.stringtypname:string;
       const
         typname:array[tstringtype] of string[8]=('',
-          'SHORTSTR','LONGSTR','ANSISTR','WIDESTR'
+          'shortstr','longstr','ansistr','widestr'
         );
       begin
         stringtypname:=typname[string_typ];
@@ -5470,7 +5470,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.73  2002-04-21 19:02:05  peter
+  Revision 1.74  2002-04-23 19:16:35  peter
+    * add pinline unit that inserts compiler supported functions using
+      one or more statements
+    * moved finalize and setlength from ninl to pinline
+
+  Revision 1.73  2002/04/21 19:02:05  peter
     * removed newn and disposen nodes, the code is now directly
       inlined from pexpr
     * -an option that will write the secondpass nodes to the .s file, this