소스 검색

* 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 년 전
부모
커밋
0f0bdabb89
3개의 변경된 파일82개의 추가작업 그리고 1개의 파일을 삭제
  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.