Browse Source

* if an absolute typeconversion changes the size, make the source not
regable. Normally this is done when the absolute typeconversion node
gets created, but the size can sometimes still change afterwards (e.g.
when removing superfluous 64 bit type conversions) (mantis #32160)

git-svn-id: trunk@37930 -

Jonas Maebe 7 years ago
parent
commit
0f0bdabb89
3 changed files with 82 additions and 1 deletions
  1. 1 0
      .gitattributes
  2. 5 1
      compiler/ncnv.pas
  3. 76 0
      tests/webtbs/tw32160.pp

+ 1 - 0
.gitattributes

@@ -15913,6 +15913,7 @@ tests/webtbs/tw3212.pp svneol=native#text/plain
 tests/webtbs/tw3214.pp svneol=native#text/plain
 tests/webtbs/tw32150.pp svneol=native#text/pascal
 tests/webtbs/tw3216.pp svneol=native#text/plain
+tests/webtbs/tw32160.pp svneol=native#text/plain
 tests/webtbs/tw3217.pp svneol=native#text/plain
 tests/webtbs/tw3222.pp svneol=native#text/plain
 tests/webtbs/tw3226.pp svneol=native#text/plain

+ 5 - 1
compiler/ncnv.pas

@@ -2366,7 +2366,11 @@ implementation
           begin
             convtype:=tc_equal;
             if (tstoreddef(resultdef).is_intregable<>tstoreddef(left.resultdef).is_intregable) or
-            (tstoreddef(resultdef).is_fpuregable<>tstoreddef(left.resultdef).is_fpuregable) then
+               (tstoreddef(resultdef).is_fpuregable<>tstoreddef(left.resultdef).is_fpuregable) or
+               { like in pdecvar.read_absolute(): if the size changes, the
+                 register size would also have to change (but second_nothing
+                 does not handle this) }
+               (tstoreddef(resultdef).size<>tstoreddef(left.resultdef).size) then
               make_not_regable(left,[ra_addr_regable]);
             exit;
           end;

+ 76 - 0
tests/webtbs/tw32160.pp

@@ -0,0 +1,76 @@
+{ %norun }
+
+unit tw32160;
+{$ifdef fpc}
+ {$mode delphi}
+{$endif}
+
+interface
+
+uses SysUtils,Classes,Math;
+
+type PPpvInt32=^PpvInt32;
+     PpvInt32=^TpvInt32;
+     TpvInt32={$ifdef fpc}Int32{$else}longint{$endif};
+
+     PPpvUInt32=^PpvUInt32;
+     PpvUInt32=^TpvUInt32;
+     TpvUInt32={$ifdef fpc}UInt32{$else}longword{$endif};
+
+     PPpvInt64=^PpvInt64;
+     PpvInt64=^TpvInt64;
+     TpvInt64=Int64;
+
+     PPpvUInt64=^PpvUInt64;
+     PpvUInt64=^TpvUInt64;
+     TpvUInt64=UInt64;
+
+     PPpvUInt128=^PpvUInt128;
+     PpvUInt128=^TpvUInt128;
+     TpvUInt128=packed record
+      public
+       class operator IntDivide(const a:TpvUInt128;const b:TpvUInt64):TpvUInt128;
+{$ifdef BIG_ENDIAN}
+       case byte of
+        0:(
+         Hi,Lo:TpvUInt64;
+        );
+        1:(
+         Q3,Q2,Q1,Q0:TpvUInt32;
+        );
+{$else}
+       case byte of
+        0:(
+         Lo,Hi:TpvUInt64;
+        );
+        1:(
+         Q0,Q1,Q2,Q3:TpvUInt32;
+        );
+ {$endif}
+     end;
+
+implementation
+
+class operator TpvUInt128.IntDivide(const a:TpvUInt128;const b:TpvUInt64):TpvUInt128;
+var Quotient:TpvUInt128;
+    Remainder:TpvUInt64;
+    Bit:TpvInt32;
+    Dividend:TpvUInt128 absolute a;
+    Divisor:TpvUInt64 absolute b;
+begin
+ Quotient:=Dividend;
+ Remainder:=0;
+ for Bit:=1 to 128 do begin
+  Remainder:=(Remainder shl 1) or (ord((Quotient.Hi and $8000000000000000)<>0) and 1);
+  Quotient.Hi:=(Quotient.Hi shl 1) or (Quotient.Lo shr 63);
+  Quotient.Lo:=Quotient.Lo shl 1;
+  if (TpvUInt32(Remainder shr 32)>TpvUInt32(Divisor shr 32)) or
+     ((TpvUInt32(Remainder shr 32)=TpvUInt32(Divisor shr 32)) and (TpvUInt32(Remainder and $ffffffff)>=TpvUInt32(Divisor and $ffffffff))) then begin
+   dec(Remainder,Divisor);
+   Quotient.Lo:=Quotient.Lo or 1;
+  end;
+ end;
+ result:=Quotient;
+end;
+
+end.