Browse Source

* unified loadnf_load_self_pointer into loadnf_load_addr
+ var parameters are now allowed when doing tail recursion optimziation, resolves #32811

git-svn-id: trunk@43824 -

florian 5 years ago
parent
commit
f6c16323fa
5 changed files with 68 additions and 23 deletions
  1. 1 0
      .gitattributes
  2. 13 12
      compiler/nld.pas
  3. 2 1
      compiler/nutils.pas
  4. 26 10
      compiler/opttail.pas
  5. 26 0
      tests/webtbs/tw32811.pp

+ 1 - 0
.gitattributes

@@ -17737,6 +17737,7 @@ tests/webtbs/tw3272b.pp svneol=native#text/pascal
 tests/webtbs/tw3274.pp svneol=native#text/plain
 tests/webtbs/tw3274.pp svneol=native#text/plain
 tests/webtbs/tw3280.pp svneol=native#text/plain
 tests/webtbs/tw3280.pp svneol=native#text/plain
 tests/webtbs/tw3281.pp svneol=native#text/plain
 tests/webtbs/tw3281.pp svneol=native#text/plain
+tests/webtbs/tw32811.pp svneol=native#text/pascal
 tests/webtbs/tw32821.pp svneol=native#text/pascal
 tests/webtbs/tw32821.pp svneol=native#text/pascal
 tests/webtbs/tw32822.pp svneol=native#text/pascal
 tests/webtbs/tw32822.pp svneol=native#text/pascal
 tests/webtbs/tw3286.pp svneol=native#text/plain
 tests/webtbs/tw3286.pp svneol=native#text/plain

+ 13 - 12
compiler/nld.pas

@@ -37,7 +37,10 @@ interface
 
 
        tloadnodeflags = (
        tloadnodeflags = (
          loadnf_is_self,
          loadnf_is_self,
-         loadnf_load_self_pointer,
+         { tell the load node the address of the symbol into the location, i.e. location^ must
+           be used to access the symbol
+           this is for example needed to load self for objects }
+         loadnf_load_addr,
          loadnf_inherited,
          loadnf_inherited,
          { the loadnode is generated internally and a varspez=vs_const should be ignore,
          { the loadnode is generated internally and a varspez=vs_const should be ignore,
            this requires that the parameter is actually passed by value
            this requires that the parameter is actually passed by value
@@ -305,7 +308,7 @@ implementation
         result:=(symtable.symtabletype=parasymtable) and
         result:=(symtable.symtabletype=parasymtable) and
                 (symtableentry.typ=paravarsym) and
                 (symtableentry.typ=paravarsym) and
                 not(vo_has_local_copy in tparavarsym(symtableentry).varoptions) and
                 not(vo_has_local_copy in tparavarsym(symtableentry).varoptions) and
-                not(loadnf_load_self_pointer in loadnodeflags) and
+                not(loadnf_load_addr in loadnodeflags) and
                 paramanager.push_addr_param(tparavarsym(symtableentry).varspez,tparavarsym(symtableentry).vardef,tprocdef(symtable.defowner).proccalloption);
                 paramanager.push_addr_param(tparavarsym(symtableentry).varspez,tparavarsym(symtableentry).vardef,tprocdef(symtable.defowner).proccalloption);
       end;
       end;
 
 
@@ -361,18 +364,16 @@ implementation
                    make_not_regable(self,[ra_different_scope]);
                    make_not_regable(self,[ra_different_scope]);
                  end;
                  end;
                resultdef:=tabstractvarsym(symtableentry).vardef;
                resultdef:=tabstractvarsym(symtableentry).vardef;
-               { self for objects is passed as var-parameter on the caller
+
+               { e.g. self for objects is passed as var-parameter on the caller
                  side, but on the callee-side we use it as a pointer ->
                  side, but on the callee-side we use it as a pointer ->
                  adjust }
                  adjust }
-               if (vo_is_self in tabstractvarsym(symtableentry).varoptions) then
-                 begin
-                   if (is_object(resultdef) or is_record(resultdef)) and
-                      (loadnf_load_self_pointer in loadnodeflags) then
-                     resultdef:=cpointerdef.getreusable(resultdef)
-                   else if (resultdef=objc_idtype) and
-                      (po_classmethod in tprocdef(symtableentry.owner.defowner).procoptions) then
-                     resultdef:=cclassrefdef.create(tprocdef(symtableentry.owner.defowner).struct)
-                 end
+               if (loadnf_load_addr in loadnodeflags) then
+                 resultdef:=cpointerdef.getreusable(resultdef);
+
+               if (vo_is_self in tabstractvarsym(symtableentry).varoptions) and (resultdef=objc_idtype) and
+                 (po_classmethod in tprocdef(symtableentry.owner.defowner).procoptions) then
+                 resultdef:=cclassrefdef.create(tprocdef(symtableentry.owner.defowner).struct)
              end;
              end;
            procsym :
            procsym :
              begin
              begin

+ 2 - 1
compiler/nutils.pas

@@ -570,7 +570,8 @@ implementation
         if assigned(srsym) then
         if assigned(srsym) then
           begin
           begin
             result:=cloadnode.create(srsym,srsym.owner);
             result:=cloadnode.create(srsym,srsym.owner);
-            include(tloadnode(result).loadnodeflags,loadnf_load_self_pointer);
+            if is_object(tabsolutevarsym(srsym).vardef) or is_record(tabsolutevarsym(srsym).vardef) then
+              include(tloadnode(result).loadnodeflags,loadnf_load_addr);
           end
           end
         else
         else
           begin
           begin

+ 26 - 10
compiler/opttail.pas

@@ -36,7 +36,7 @@ unit opttail;
       globtype,
       globtype,
       symconst,symsym,
       symconst,symsym,
       defcmp,defutil,
       defcmp,defutil,
-      nutils,nbas,nflw,ncal,nld,ncnv,
+      nutils,nbas,nflw,ncal,nld,ncnv,nmem,
       pass_1,
       pass_1,
       paramgr;
       paramgr;
 
 
@@ -120,20 +120,36 @@ unit opttail;
                     paranode:=tcallparanode(usedcallnode.left);
                     paranode:=tcallparanode(usedcallnode.left);
                     while assigned(paranode) do
                     while assigned(paranode) do
                       begin
                       begin
-                        tempnode:=ctempcreatenode.create(paranode.left.resultdef,paranode.left.resultdef.size,tt_persistent,true);
-                        addstatement(calcstatements,tempnode);
-                        addstatement(calcstatements,
-                          cassignmentnode.create(
-                            ctemprefnode.create(tempnode),
-                            paranode.left
-                            ));
+                        if paranode.parasym.varspez=vs_var then
+                          begin
+                            tempnode:=ctempcreatenode.create(voidcodepointertype,voidcodepointertype.size,tt_persistent,true);
+                            addstatement(calcstatements,tempnode);
+                            addstatement(calcstatements,
+                              cassignmentnode.create(
+                                ctemprefnode.create(tempnode),
+                                caddrnode.create_internal(paranode.left)
+                                ));
+                          end
+                        else
+                          begin
+                            tempnode:=ctempcreatenode.create(paranode.left.resultdef,paranode.left.resultdef.size,tt_persistent,true);
+                            addstatement(calcstatements,tempnode);
+                            addstatement(calcstatements,
+                              cassignmentnode.create_internal(
+                                ctemprefnode.create(tempnode),
+                                paranode.left
+                                ));
+                          end;
 
 
                         { "cast" away const varspezs }
                         { "cast" away const varspezs }
                         loadnode:=cloadnode.create(paranode.parasym,paranode.parasym.owner);
                         loadnode:=cloadnode.create(paranode.parasym,paranode.parasym.owner);
                         include(tloadnode(loadnode).loadnodeflags,loadnf_isinternal_ignoreconst);
                         include(tloadnode(loadnode).loadnodeflags,loadnf_isinternal_ignoreconst);
 
 
+                        { load the address of the symbol instead of symbol }
+                        if paranode.parasym.varspez=vs_var then
+                          include(tloadnode(loadnode).loadnodeflags,loadnf_load_addr);
                         addstatement(copystatements,
                         addstatement(copystatements,
-                          cassignmentnode.create(
+                          cassignmentnode.create_internal(
                             loadnode,
                             loadnode,
                             ctemprefnode.create(tempnode)
                             ctemprefnode.create(tempnode)
                             ));
                             ));
@@ -190,7 +206,7 @@ unit opttail;
         { check if the parameters actually would support tail recursion elimination }
         { check if the parameters actually would support tail recursion elimination }
         for i:=0 to p.paras.count-1 do
         for i:=0 to p.paras.count-1 do
           with tparavarsym(p.paras[i]) do
           with tparavarsym(p.paras[i]) do
-            if (varspez in [vs_out,vs_var,vs_constref]) or
+            if (varspez in [vs_out,{vs_var,}vs_constref]) or
               ((varspez=vs_const) and
               ((varspez=vs_const) and
                (paramanager.push_addr_param(varspez,vardef,p.proccalloption)) or
                (paramanager.push_addr_param(varspez,vardef,p.proccalloption)) or
                { parameters requiring tables are too complicated to handle
                { parameters requiring tables are too complicated to handle

+ 26 - 0
tests/webtbs/tw32811.pp

@@ -0,0 +1,26 @@
+
+type
+  pnode = ^node;
+  node = record
+    i: integer;
+    left: pnode;
+    right: pnode;
+  end;
+
+procedure insert(var t: pnode; i: integer);
+begin
+  if t = nil then
+    begin
+      new(t);
+      t^.i := i;
+      t^.left := nil;
+      t^.right := nil;
+    end
+  else
+    if i < t^.i
+      then insert(t^.left, i)
+      else insert(t^.right, i);
+end;
+
+begin
+end.