浏览代码

* fixed register allocation info when initialising parameters, both in
case they are refcounted out-parameters and when using -gt (mantis #16757)

git-svn-id: trunk@15479 -

Jonas Maebe 15 年之前
父节点
当前提交
7321f9a87a
共有 3 个文件被更改,包括 45 次插入10 次删除
  1. 1 0
      .gitattributes
  2. 18 10
      compiler/ncgutil.pas
  3. 26 0
      tests/webtbs/tw16757.pp

+ 1 - 0
.gitattributes

@@ -10517,6 +10517,7 @@ tests/webtbs/tw16402.pp svneol=native#text/plain
 tests/webtbs/tw1658.pp svneol=native#text/plain
 tests/webtbs/tw16668.pp svneol=native#text/plain
 tests/webtbs/tw16700.pp svneol=native#text/plain
+tests/webtbs/tw16757.pp svneol=native#text/plain
 tests/webtbs/tw1677.pp svneol=native#text/plain
 tests/webtbs/tw16770.pp svneol=native#text/plain
 tests/webtbs/tw16772.pp svneol=native#text/plain

+ 18 - 10
compiler/ncgutil.pas

@@ -2067,6 +2067,23 @@ implementation
         if (tppcprocinfo(current_procinfo).needs_frame_pointer) then
           cg.a_reg_dealloc(list, NR_OLD_STACK_POINTER_REG);
 {$endif powerpc64}
+        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;
 
 
@@ -2091,21 +2108,12 @@ implementation
                TSymtable(current_module.localsymtable).SymList.ForEachCall(@initialize_regvars,list);
              end;
            else
-             begin
-               if (localvartrashing <> -1) and
-                  not(po_assembler in current_procinfo.procdef.procoptions) then
-                 current_procinfo.procdef.localst.SymList.ForEachCall(@trash_variable,list);
-               current_procinfo.procdef.localst.SymList.ForEachCall(@initialize_data,list);
-             end;
+             current_procinfo.procdef.localst.SymList.ForEachCall(@initialize_data,list);
         end;
 
         { initialisizes temp. ansi/wide string data }
         inittempvariables(list);
 
-        { initialize ansi/widesstring para's }
-        if not(po_assembler in current_procinfo.procdef.procoptions) then
-          current_procinfo.procdef.parast.SymList.ForEachCall(@init_paras,list);
-
 {$ifdef OLDREGVARS}
         load_regvars(list,nil);
 {$endif OLDREGVARS}

+ 26 - 0
tests/webtbs/tw16757.pp

@@ -0,0 +1,26 @@
+{ %opt=-g-t }
+program project1;
+{$mode objfpc}{$H+}
+
+uses Classes;
+
+type
+TBar = class
+  function foo(StockID: LongInt; out Image, Mask: Longint): Boolean;
+end;
+
+function TBar.foo(StockID: LongInt; out Image, Mask: Longint): Boolean;
+begin
+  Result := False;
+end;
+
+var
+  a: array[0..10000] of longint;
+  i: longint;
+  x:TBar;
+begin
+  x.foo(0,a[0],a[1]);
+  for i:=2 to high(a) do
+    if a[i]<>0 then
+      halt(1);
+end.