Browse Source

+ hlcg implementation of gen_load_para_value(); no support yet for copying
value parameters when necessary, nor for -gt variable trashing

git-svn-id: branches/jvmbackend@18367 -

Jonas Maebe 14 years ago
parent
commit
09207563d5
3 changed files with 135 additions and 1 deletions
  1. 7 0
      compiler/hlcg2ll.pas
  2. 127 0
      compiler/hlcgobj.pas
  3. 1 1
      compiler/psub.pas

+ 7 - 0
compiler/hlcg2ll.pas

@@ -394,6 +394,8 @@ unit hlcg2ll;
 
 
           procedure maketojumpbool(list:TAsmList; p : tnode);override;
           procedure maketojumpbool(list:TAsmList; p : tnode);override;
 
 
+          procedure gen_load_para_value(list:TAsmList);override;
+
           procedure gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara); override;
           procedure gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara); override;
           procedure gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean); override;
           procedure gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean); override;
        end;
        end;
@@ -1163,6 +1165,11 @@ procedure thlcg2ll.a_loadaddr_ref_reg(list: TAsmList; fromsize, tosize: tdef; co
       ncgutil.maketojumpbool(list,p,lr_dont_load_regvars);
       ncgutil.maketojumpbool(list,p,lr_dont_load_regvars);
     end;
     end;
 
 
+  procedure thlcg2ll.gen_load_para_value(list: TAsmList);
+    begin
+      ncgutil.gen_load_para_value(list);
+    end;
+
   procedure thlcg2ll.gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara);
   procedure thlcg2ll.gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara);
     begin
     begin
       ncgutil.gen_load_loc_cgpara(list,vardef,l,cgpara);
       ncgutil.gen_load_loc_cgpara(list,vardef,l,cgpara);

+ 127 - 0
compiler/hlcgobj.pas

@@ -426,6 +426,8 @@ unit hlcgobj;
           procedure gen_proc_symbol(list:TAsmList);virtual;
           procedure gen_proc_symbol(list:TAsmList);virtual;
           procedure gen_proc_symbol_end(list:TAsmList);virtual;
           procedure gen_proc_symbol_end(list:TAsmList);virtual;
 
 
+          procedure gen_load_para_value(list:TAsmList);virtual;
+
          private
          private
           procedure gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation;const cgpara: tcgpara;locintsize: longint);virtual;
           procedure gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation;const cgpara: tcgpara;locintsize: longint);virtual;
          protected
          protected
@@ -1825,6 +1827,131 @@ implementation
         end;
         end;
     end;
     end;
 
 
+  { generates the code for incrementing the reference count of parameters and
+    initialize out parameters }
+  procedure init_paras(p:TObject;arg:pointer);
+    var
+      href : treference;
+      tmpreg : tregister;
+      list : TAsmList;
+      needs_inittable (*,
+      do_trashing     *)  : boolean;
+    begin
+      list:=TAsmList(arg);
+      if (tsym(p).typ=paravarsym) then
+       begin
+         needs_inittable:=is_managed_type(tparavarsym(p).vardef);
+(*
+         do_trashing:=
+           (localvartrashing <> -1) and
+           (not assigned(tparavarsym(p).defaultconstsym)) and
+           not needs_inittable;
+*)
+         case tparavarsym(p).varspez of
+           vs_value :
+             if needs_inittable then
+               begin
+                 { variants are already handled by the call to fpc_variant_copy_overwrite if
+                   they are passed by reference }
+                 if not((tparavarsym(p).vardef.typ=variantdef) and
+                   paramanager.push_addr_param(tparavarsym(p).varspez,tparavarsym(p).vardef,current_procinfo.procdef.proccalloption)) then
+                   begin
+                     location_get_data_ref(list,tparavarsym(p).initialloc,href,is_open_array(tparavarsym(p).vardef),sizeof(pint));
+                     hlcg.g_incrrefcount(list,tparavarsym(p).vardef,href);
+                   end;
+               end;
+           vs_out :
+             begin
+               if needs_inittable (*or
+                  do_trashing*) then
+                 begin
+                   tmpreg:=cg.getaddressregister(list);
+                   hlcg.a_load_loc_reg(list,tparavarsym(p).vardef,tparavarsym(p).vardef,tparavarsym(p).initialloc,tmpreg);
+                   { we have no idea about the alignment at the callee side,
+                     and the user also cannot specify "unaligned" here, so
+                     assume worst case }
+                   reference_reset_base(href,tmpreg,0,1);
+(*
+                   if do_trashing and
+                      { needs separate implementation to trash open arrays }
+                      { since their size is only known at run time         }
+                      not is_special_array(tparavarsym(p).vardef) then
+                      { may be an open string, even if is_open_string() returns }
+                      { false (for some helpers in the system unit)             }
+                     if not is_shortstring(tparavarsym(p).vardef) then
+                       trash_reference(list,href,tparavarsym(p).vardef.size)
+                     else
+                       trash_reference(list,href,2);
+*)
+                   if needs_inittable then
+                     hlcg.g_initialize(list,tparavarsym(p).vardef,href);
+                 end;
+             end;
+(*
+           else if do_trashing and
+                   ([vo_is_funcret,vo_is_hidden_para] * tparavarsym(p).varoptions = [vo_is_funcret,vo_is_hidden_para]) then
+                 begin
+                   tmpreg:=cg.getaddressregister(list);
+                   a_load_loc_reg(list,tparavarsym(p).vardef,tparavarsym(p).vardef,tparavarsym(p).initialloc,tmpreg);
+                   { should always have standard alignment. If a function is assigned
+                     to a non-aligned variable, the optimisation to pass this variable
+                     directly as hidden function result must/cannot be performed
+                     (see tcallnode.funcret_can_be_reused)
+                   }
+                   reference_reset_base(href,tmpreg,0,
+                     used_align(tparavarsym(p).vardef.alignment,current_settings.alignment.localalignmin,current_settings.alignment.localalignmax));
+                   { may be an open string, even if is_open_string() returns }
+                   { false (for some helpers in the system unit)             }
+                   if not is_shortstring(tparavarsym(p).vardef) then
+                     trash_reference(list,href,tparavarsym(p).vardef.size)
+                   else
+                     { an open string has at least size 2 }
+                     trash_reference(list,href,2);
+                 end
+*)
+         end;
+       end;
+    end;
+
+  procedure thlcgobj.gen_load_para_value(list: TAsmList);
+    var
+      i: longint;
+      currpara: tparavarsym;
+    begin
+      if (po_assembler in current_procinfo.procdef.procoptions) then
+        exit;
+
+      { Copy parameters to local references/registers }
+      for i:=0 to current_procinfo.procdef.paras.count-1 do
+        begin
+          currpara:=tparavarsym(current_procinfo.procdef.paras[i]);
+          gen_load_cgpara_loc(list,currpara.vardef,currpara.paraloc[calleeside],currpara.initialloc,paramanager.param_use_paraloc(currpara.paraloc[calleeside]));
+        end;
+
+      { generate copies of call by value parameters, must be done before
+        the initialization and body is parsed because the refcounts are
+        incremented using the local copies }
+//      current_procinfo.procdef.parast.SymList.ForEachCall(@copyvalueparas,list);
+
+      if not(po_assembler in current_procinfo.procdef.procoptions) then
+        begin
+          { has to be done here rather than in gen_initialize_code, because
+            the initialisation code is generated a) later and b) with
+            rad_backwards, so the register allocator would generate
+            information as if this code comes before loading the parameters
+            from their original registers to their local location }
+//          if (localvartrashing <> -1) then
+//            current_procinfo.procdef.localst.SymList.ForEachCall(@trash_variable,list);
+          { initialize refcounted paras, and trash others. Needed here
+            instead of in gen_initialize_code, because when a reference is
+            intialised or trashed while the pointer to that reference is kept
+            in a regvar, we add a register move and that one again has to
+            come after the parameter loading code as far as the register
+            allocator is concerned }
+          current_procinfo.procdef.parast.SymList.ForEachCall(@init_paras,list);
+        end;
+    end;
+
   procedure thlcgobj.gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation; const cgpara: tcgpara; locintsize: longint);
   procedure thlcgobj.gen_loadfpu_loc_cgpara(list: TAsmList; size: tdef; const l: tlocation; const cgpara: tcgpara; locintsize: longint);
     begin
     begin
       case l.loc of
       case l.loc of

+ 1 - 1
compiler/psub.pas

@@ -1049,7 +1049,7 @@ implementation
 {$endif oldreg}
 {$endif oldreg}
             current_filepos:=entrypos;
             current_filepos:=entrypos;
 
 
-            gen_load_para_value(templist);
+            hlcg.gen_load_para_value(templist);
 
 
             { caller paraloc info is also necessary in the stackframe_entry
             { caller paraloc info is also necessary in the stackframe_entry
               code of the ppc (and possibly other processors)               }
               code of the ppc (and possibly other processors)               }