* 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 -
This commit is contained in:
Jonas Maebe 2018-01-07 15:37:23 +00:00
parent 8714ddafa5
commit 0f0bdabb89
3 changed files with 82 additions and 1 deletions

1
.gitattributes vendored
View File

@ -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

View File

@ -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
tests/webtbs/tw32160.pp Normal file
View File

@ -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.