Browse Source

* passing a var parameter to var parameter is now also allowed
for register locations (=regvars)

peter 21 years ago
parent
commit
0573c742e4
2 changed files with 60 additions and 45 deletions
  1. 35 20
      compiler/ncgcal.pas
  2. 25 25
      compiler/ncgld.pas

+ 35 - 20
compiler/ncgcal.pas

@@ -428,20 +428,33 @@ implementation
                      paramanager.push_addr_param(paraitem.paratyp,paraitem.paratype.def,
                          aktcallnode.procdefinition.proccalloption)) then
                    begin
-                      { Check for passing a constant to var,out parameter }
-                      if (paraitem.paratyp in [vs_var,vs_out]) and
-                         (left.location.loc<>LOC_REFERENCE) then
-                       begin
-                         { passing self to a var parameter is allowed in
-                           TP and delphi }
-                         if not((left.location.loc=LOC_CREFERENCE) and
-                                is_self_node(left)) then
-                          internalerror(200106041);
-                       end;
-                      { Force to be in memory }
-                      if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
-                        location_force_mem(exprasmlist,left.location);
-                      push_addr_para;
+                      { Passing a var parameter to a var parameter, we can
+                        just push the address transparently }
+                      if (left.nodetype=loadn) and
+                         (tloadnode(left).is_addr_param_load) then
+                        begin
+                          if (left.location.reference.index<>NR_NO) or
+                             (left.location.reference.offset<>0) then
+                            internalerror(200410107);
+                          cg.a_param_reg(exprasmlist,OS_ADDR,left.location.reference.base,tempcgpara)
+                        end
+                      else
+                        begin
+                          { Check for passing a constant to var,out parameter }
+                          if (paraitem.paratyp in [vs_var,vs_out]) and
+                             (left.location.loc<>LOC_REFERENCE) then
+                           begin
+                             { passing self to a var parameter is allowed in
+                               TP and delphi }
+                             if not((left.location.loc=LOC_CREFERENCE) and
+                                    is_self_node(left)) then
+                              internalerror(200106041);
+                           end;
+                          { Force to be in memory }
+                          if not(left.location.loc in [LOC_CREFERENCE,LOC_REFERENCE]) then
+                            location_force_mem(exprasmlist,left.location);
+                          push_addr_para;
+                        end;
                    end
                  else
                    push_value_para;
@@ -1049,8 +1062,7 @@ implementation
          { Allocate parameters and locals }
          gen_alloc_inline_parast(exprasmlist,tprocdef(procdefinition));
          gen_alloc_inline_funcret(exprasmlist,tprocdef(procdefinition));
-         if tprocdef(procdefinition).localst.symtabletype=localsymtable then
-           gen_alloc_localst(exprasmlist,tlocalsymtable(tprocdef(procdefinition).localst));
+         gen_alloc_symtable(exprasmlist,tlocalsymtable(tprocdef(procdefinition).localst));
 
          { if we allocate the temp. location for ansi- or widestrings }
          { already here, we avoid later a push/pop                    }
@@ -1183,9 +1195,8 @@ implementation
            end;
 
          { Release parameters and locals }
-         gen_free_parast(exprasmlist,tparasymtable(current_procinfo.procdef.parast));
-         if current_procinfo.procdef.localst.symtabletype=localsymtable then
-           gen_free_localst(exprasmlist,tlocalsymtable(current_procinfo.procdef.localst));
+         gen_free_symtable(exprasmlist,tparasymtable(current_procinfo.procdef.parast));
+         gen_free_symtable(exprasmlist,tlocalsymtable(current_procinfo.procdef.localst));
 
 {$ifdef GDB}
          if (cs_debuginfo in aktmoduleswitches) and
@@ -1232,7 +1243,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.176  2004-09-27 15:15:20  peter
+  Revision 1.177  2004-10-10 20:21:18  peter
+    * passing a var parameter to var parameter is now also allowed
+      for register locations (=regvars)
+
+  Revision 1.176  2004/09/27 15:15:20  peter
     * dealloc function result registers, register allocation is now
       back at pre-paraloc level
 

+ 25 - 25
compiler/ncgld.pas

@@ -119,13 +119,8 @@ implementation
                begin
                   symtabletype:=symtable.symtabletype;
                   hregister:=NR_NO;
-                  { C variable }
-                  if (vo_is_C_var in tvarsym(symtableentry).varoptions) then
-                    begin
-                       location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA);
-                    end
                   { DLL variable }
-                  else if (vo_is_dll_var in tvarsym(symtableentry).varoptions) then
+                  if (vo_is_dll_var in tvarsym(symtableentry).varoptions) then
                     begin
                       if target_info.system=system_powerpc_darwin then
                         begin
@@ -141,12 +136,7 @@ implementation
                           reference_reset_base(location.reference,hregister,0);
                         end;
                     end
-                  { external variable }
-                  else if (vo_is_external in tvarsym(symtableentry).varoptions) then
-                    begin
-                      location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA);
-                    end
-                  { thread variable }
+                  { Thread variable }
                   else if (vo_is_thread_var in tvarsym(symtableentry).varoptions) then
                     begin
                        {
@@ -192,7 +182,7 @@ implementation
                        cg.a_label(exprasmlist,endrelocatelab);
                        location.reference.base:=hregister;
                     end
-                  { nested variable }
+                  { Nested variable }
                   else if assigned(left) then
                     begin
                       if not(symtabletype in [localsymtable,parasymtable]) then
@@ -205,7 +195,7 @@ implementation
                       hregister:=left.location.register;
                       reference_reset_base(location.reference,hregister,tvarsym(symtableentry).localloc.reference.offset);
                     end
-                  { normal variable }
+                  { Normal (or external) variable }
                   else
                     begin
 {$ifdef OLDREGVARS}
@@ -246,7 +236,12 @@ implementation
                                         internalerror(200403023);
                                     end
                                   else
-                                    location.reference.symbol:=objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA);
+                                    begin
+                                      if tvarsym(symtableentry).localloc.loc=LOC_INVALID then
+                                        reference_reset_symbol(location.reference,objectlibrary.newasmsymbol(tvarsym(symtableentry).mangledname,AB_EXTERNAL,AT_DATA),0)
+                                      else
+                                        location:=tvarsym(symtableentry).localloc;
+                                    end;
                                 end;
                               else
                                 internalerror(200305102);
@@ -257,16 +252,17 @@ implementation
                   { handle call by reference variables when they are not
                     alreayd copied to local copies. Also ignore the reference
                     when we need to load the self pointer for objects }
-                  if (symtabletype=parasymtable) and
-                     not(vo_has_local_copy in tvarsym(symtableentry).varoptions) and
-                     not(nf_load_self_pointer in flags) and
-                     paramanager.push_addr_param(tvarsym(symtableentry).varspez,tvarsym(symtableentry).vartype.def,tprocdef(symtable.defowner).proccalloption) then
+                  if is_addr_param_load then
                     begin
-                      if hregister=NR_NO then
-                        hregister:=cg.getaddressregister(exprasmlist);
-                      { we need to load only an address }
-                      location.size:=OS_ADDR;
-                      cg.a_load_loc_reg(exprasmlist,location.size,location,hregister);
+                      if (location.loc in [LOC_CREGISTER,LOC_REGISTER]) then
+                        hregister:=location.register
+                      else
+                        begin
+                          hregister:=cg.getaddressregister(exprasmlist);
+                          { we need to load only an address }
+                          location.size:=OS_ADDR;
+                          cg.a_load_loc_reg(exprasmlist,location.size,location,hregister);
+                        end;
                       location_reset(location,LOC_REFERENCE,newsize);
                       location.reference.base:=hregister;
                     end;
@@ -927,7 +923,11 @@ begin
 end.
 {
   $Log$
-  Revision 1.126  2004-09-26 17:45:30  peter
+  Revision 1.127  2004-10-10 20:21:18  peter
+    * passing a var parameter to var parameter is now also allowed
+      for register locations (=regvars)
+
+  Revision 1.126  2004/09/26 17:45:30  peter
     * simple regvar support, not yet finished
 
   Revision 1.125  2004/09/25 14:23:54  peter