mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-15 11:29:34 +02:00
* factored out the conditions under which add nodes need to perform
overflow checks o in particular ensure that cpu-specific overrides don't perform overflow checks when nf_internal is set git-svn-id: trunk@42573 -
This commit is contained in:
parent
c70f2c63cd
commit
ce598c15ec
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -12926,6 +12926,7 @@ tests/tbs/tb0654.pp svneol=native#text/plain
|
|||||||
tests/tbs/tb0655.pp svneol=native#text/pascal
|
tests/tbs/tb0655.pp svneol=native#text/pascal
|
||||||
tests/tbs/tb0656.pp svneol=native#text/pascal
|
tests/tbs/tb0656.pp svneol=native#text/pascal
|
||||||
tests/tbs/tb0657.pp svneol=native#text/pascal
|
tests/tbs/tb0657.pp svneol=native#text/pascal
|
||||||
|
tests/tbs/tb0658.pp svneol=native#text/plain
|
||||||
tests/tbs/tb205.pp svneol=native#text/plain
|
tests/tbs/tb205.pp svneol=native#text/plain
|
||||||
tests/tbs/tb610.pp svneol=native#text/pascal
|
tests/tbs/tb610.pp svneol=native#text/pascal
|
||||||
tests/tbs/tb613.pp svneol=native#text/plain
|
tests/tbs/tb613.pp svneol=native#text/plain
|
||||||
|
@ -728,7 +728,7 @@ interface
|
|||||||
begin
|
begin
|
||||||
result:=GenerateThumbCode or
|
result:=GenerateThumbCode or
|
||||||
not(CPUARM_HAS_UMULL in cpu_capabilities[current_settings.cputype]) or
|
not(CPUARM_HAS_UMULL in cpu_capabilities[current_settings.cputype]) or
|
||||||
(cs_check_overflow in current_settings.localswitches);
|
needoverflowcheck;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
@ -64,7 +64,7 @@ interface
|
|||||||
|
|
||||||
function ti386addnode.use_generic_mul64bit: boolean;
|
function ti386addnode.use_generic_mul64bit: boolean;
|
||||||
begin
|
begin
|
||||||
result:=(cs_check_overflow in current_settings.localswitches) or
|
result:=needoverflowcheck or
|
||||||
(cs_opt_size in current_settings.optimizerswitches);
|
(cs_opt_size in current_settings.optimizerswitches);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ interface
|
|||||||
not(is_signed(right.resultdef));
|
not(is_signed(right.resultdef));
|
||||||
{ use IMUL instead of MUL in case overflow checking is off and we're
|
{ use IMUL instead of MUL in case overflow checking is off and we're
|
||||||
doing a 32->32-bit multiplication }
|
doing a 32->32-bit multiplication }
|
||||||
if not (cs_check_overflow in current_settings.localswitches) and
|
if not needoverflowcheck and
|
||||||
not is_64bit(resultdef) then
|
not is_64bit(resultdef) then
|
||||||
unsigned:=false;
|
unsigned:=false;
|
||||||
if (nodetype=muln) and (unsigned or is_64bit(resultdef)) then
|
if (nodetype=muln) and (unsigned or is_64bit(resultdef)) then
|
||||||
@ -213,7 +213,7 @@ interface
|
|||||||
{ is in unsigned VAR!! }
|
{ is in unsigned VAR!! }
|
||||||
if mboverflow then
|
if mboverflow then
|
||||||
begin
|
begin
|
||||||
if cs_check_overflow in current_settings.localswitches then
|
if needoverflowcheck then
|
||||||
begin
|
begin
|
||||||
current_asmdata.getjumplabel(hl4);
|
current_asmdata.getjumplabel(hl4);
|
||||||
if unsigned then
|
if unsigned then
|
||||||
@ -487,7 +487,7 @@ interface
|
|||||||
emit_ref(asmops[unsigned],S_L,ref)
|
emit_ref(asmops[unsigned],S_L,ref)
|
||||||
else
|
else
|
||||||
emit_reg(asmops[unsigned],S_L,reg);
|
emit_reg(asmops[unsigned],S_L,reg);
|
||||||
if (cs_check_overflow in current_settings.localswitches) and
|
if needoverflowcheck and
|
||||||
{ 32->64 bit cannot overflow }
|
{ 32->64 bit cannot overflow }
|
||||||
(not is_64bit(resultdef)) then
|
(not is_64bit(resultdef)) then
|
||||||
begin
|
begin
|
||||||
|
@ -315,7 +315,7 @@ interface
|
|||||||
{ is in unsigned VAR!! }
|
{ is in unsigned VAR!! }
|
||||||
if mboverflow then
|
if mboverflow then
|
||||||
begin
|
begin
|
||||||
if cs_check_overflow in current_settings.localswitches then
|
if needoverflowcheck then
|
||||||
begin
|
begin
|
||||||
current_asmdata.getjumplabel(hl4);
|
current_asmdata.getjumplabel(hl4);
|
||||||
if unsigned then
|
if unsigned then
|
||||||
@ -1002,6 +1002,7 @@ interface
|
|||||||
ref:Treference;
|
ref:Treference;
|
||||||
use_ref:boolean;
|
use_ref:boolean;
|
||||||
hl4 : tasmlabel;
|
hl4 : tasmlabel;
|
||||||
|
overflowcheck: boolean;
|
||||||
|
|
||||||
const
|
const
|
||||||
asmops: array[boolean] of tasmop = (A_IMUL, A_MUL);
|
asmops: array[boolean] of tasmop = (A_IMUL, A_MUL);
|
||||||
@ -1012,10 +1013,12 @@ interface
|
|||||||
|
|
||||||
pass_left_right;
|
pass_left_right;
|
||||||
|
|
||||||
|
overflowcheck:=needoverflowcheck;
|
||||||
|
|
||||||
{ MUL is faster than IMUL on the 8086 & 8088 (and equal in speed on 286+),
|
{ MUL is faster than IMUL on the 8086 & 8088 (and equal in speed on 286+),
|
||||||
but it's only safe to use in place of IMUL when overflow checking is off
|
but it's only safe to use in place of IMUL when overflow checking is off
|
||||||
and we're doing a 16-bit>16-bit multiplication }
|
and we're doing a 16-bit>16-bit multiplication }
|
||||||
if not (cs_check_overflow in current_settings.localswitches) and
|
if not overflowcheck and
|
||||||
(not is_32bitint(resultdef)) then
|
(not is_32bitint(resultdef)) then
|
||||||
unsigned:=true;
|
unsigned:=true;
|
||||||
|
|
||||||
@ -1048,7 +1051,7 @@ interface
|
|||||||
emit_ref(asmops[unsigned],S_W,ref)
|
emit_ref(asmops[unsigned],S_W,ref)
|
||||||
else
|
else
|
||||||
emit_reg(asmops[unsigned],S_W,reg);
|
emit_reg(asmops[unsigned],S_W,reg);
|
||||||
if (cs_check_overflow in current_settings.localswitches) and
|
if overflowcheck and
|
||||||
{ 16->32 bit cannot overflow }
|
{ 16->32 bit cannot overflow }
|
||||||
(not is_32bitint(resultdef)) then
|
(not is_32bitint(resultdef)) then
|
||||||
begin
|
begin
|
||||||
|
@ -399,9 +399,7 @@ implementation
|
|||||||
begin
|
begin
|
||||||
{ if we need to handle overflow checking, fall back to the generic cg }
|
{ if we need to handle overflow checking, fall back to the generic cg }
|
||||||
if (nodetype in [addn,subn,muln]) and
|
if (nodetype in [addn,subn,muln]) and
|
||||||
(left.resultdef.typ<>pointerdef) and
|
needoverflowcheck then
|
||||||
(right.resultdef.typ<>pointerdef) and
|
|
||||||
(cs_check_overflow in current_settings.localswitches) then
|
|
||||||
begin
|
begin
|
||||||
inherited;
|
inherited;
|
||||||
exit;
|
exit;
|
||||||
@ -609,7 +607,7 @@ implementation
|
|||||||
|
|
||||||
function t68kaddnode.use_generic_mul64bit: boolean;
|
function t68kaddnode.use_generic_mul64bit: boolean;
|
||||||
begin
|
begin
|
||||||
result:=(cs_check_overflow in current_settings.localswitches) or
|
result:=needoverflowcheck or
|
||||||
(cs_opt_size in current_settings.optimizerswitches) or
|
(cs_opt_size in current_settings.optimizerswitches) or
|
||||||
not (CPUM68K_HAS_64BITMUL in cpu_capabilities[current_settings.cputype]);
|
not (CPUM68K_HAS_64BITMUL in cpu_capabilities[current_settings.cputype]);
|
||||||
end;
|
end;
|
||||||
|
@ -426,7 +426,7 @@ end;
|
|||||||
|
|
||||||
function tmipsaddnode.use_generic_mul64bit: boolean;
|
function tmipsaddnode.use_generic_mul64bit: boolean;
|
||||||
begin
|
begin
|
||||||
result:=(cs_check_overflow in current_settings.localswitches) or
|
result:=needoverflowcheck or
|
||||||
(not (CPUMIPS_HAS_ISA32R2 in cpu_capabilities[current_settings.cputype]));
|
(not (CPUMIPS_HAS_ISA32R2 in cpu_capabilities[current_settings.cputype]));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -66,6 +66,8 @@ interface
|
|||||||
procedure second_cmpsmallset;virtual;abstract;
|
procedure second_cmpsmallset;virtual;abstract;
|
||||||
procedure second_cmp64bit;virtual;abstract;
|
procedure second_cmp64bit;virtual;abstract;
|
||||||
procedure second_cmpordinal;virtual;abstract;
|
procedure second_cmpordinal;virtual;abstract;
|
||||||
|
|
||||||
|
function needoverflowcheck: boolean;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
implementation
|
implementation
|
||||||
@ -518,9 +520,7 @@ interface
|
|||||||
|
|
||||||
checkoverflow:=
|
checkoverflow:=
|
||||||
checkoverflow and
|
checkoverflow and
|
||||||
(left.resultdef.typ<>pointerdef) and
|
needoverflowcheck;
|
||||||
(right.resultdef.typ<>pointerdef) and
|
|
||||||
(cs_check_overflow in current_settings.localswitches) and not(nf_internal in flags);
|
|
||||||
|
|
||||||
{$if defined(cpu64bitalu) or defined(cpuhighleveltarget)}
|
{$if defined(cpu64bitalu) or defined(cpuhighleveltarget)}
|
||||||
case nodetype of
|
case nodetype of
|
||||||
@ -763,6 +763,15 @@ interface
|
|||||||
second_cmpordinal;
|
second_cmpordinal;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function tcgaddnode.needoverflowcheck: boolean;
|
||||||
|
begin
|
||||||
|
result:=
|
||||||
|
(cs_check_overflow in current_settings.localswitches) and
|
||||||
|
(left.resultdef.typ<>pointerdef) and
|
||||||
|
(right.resultdef.typ<>pointerdef) and
|
||||||
|
not(nf_internal in flags);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
{*****************************************************************************
|
{*****************************************************************************
|
||||||
pass_generate_code;
|
pass_generate_code;
|
||||||
|
@ -325,11 +325,10 @@ interface
|
|||||||
current_asmdata.getjumplabel(falselabel);
|
current_asmdata.getjumplabel(falselabel);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
load_left_right(cmpop,((cs_check_overflow in current_settings.localswitches) and
|
load_left_right(cmpop,needoverflowcheck or (nodetype = muln));
|
||||||
(nodetype in [addn,subn])) or (nodetype = muln));
|
|
||||||
|
|
||||||
if (nodetype <> muln) and
|
if (nodetype<>muln) and
|
||||||
(not(cs_check_overflow in current_settings.localswitches) or
|
(not needoverflowcheck or
|
||||||
not(nodetype in [addn,subn])) then
|
not(nodetype in [addn,subn])) then
|
||||||
begin
|
begin
|
||||||
case nodetype of
|
case nodetype of
|
||||||
@ -657,9 +656,7 @@ interface
|
|||||||
|
|
||||||
checkoverflow:=
|
checkoverflow:=
|
||||||
(nodetype in [addn,subn,muln]) and
|
(nodetype in [addn,subn,muln]) and
|
||||||
(cs_check_overflow in current_settings.localswitches) and
|
needoverflowcheck;
|
||||||
(left.resultdef.typ<>pointerdef) and
|
|
||||||
(right.resultdef.typ<>pointerdef);
|
|
||||||
|
|
||||||
load_left_right(cmpop, checkoverflow);
|
load_left_right(cmpop, checkoverflow);
|
||||||
|
|
||||||
|
@ -219,11 +219,7 @@ begin
|
|||||||
else
|
else
|
||||||
location_reset(location, LOC_FLAGS, OS_NO);
|
location_reset(location, LOC_FLAGS, OS_NO);
|
||||||
|
|
||||||
checkoverflow:=
|
checkoverflow:=needoverflowcheck;
|
||||||
(nodetype in [addn,subn,muln]) and
|
|
||||||
(cs_check_overflow in current_settings.localswitches) and
|
|
||||||
(left.resultdef.typ<>pointerdef) and
|
|
||||||
(right.resultdef.typ<>pointerdef);
|
|
||||||
|
|
||||||
load_left_right(cmpop, checkoverflow);
|
load_left_right(cmpop, checkoverflow);
|
||||||
|
|
||||||
|
@ -505,7 +505,7 @@ interface
|
|||||||
function tsparcaddnode.use_generic_mul64bit: boolean;
|
function tsparcaddnode.use_generic_mul64bit: boolean;
|
||||||
begin
|
begin
|
||||||
{$ifdef SPARC64}
|
{$ifdef SPARC64}
|
||||||
result:=(cs_check_overflow in current_settings.localswitches);
|
result:=needoverflowcheck;
|
||||||
{$else SPARC64}
|
{$else SPARC64}
|
||||||
result:=inherited;
|
result:=inherited;
|
||||||
{$endif SPARC64}
|
{$endif SPARC64}
|
||||||
|
@ -93,7 +93,9 @@ unit nx86add;
|
|||||||
hl4 : tasmlabel;
|
hl4 : tasmlabel;
|
||||||
r : Tregister;
|
r : Tregister;
|
||||||
href : treference;
|
href : treference;
|
||||||
|
overflowcheck: boolean;
|
||||||
begin
|
begin
|
||||||
|
overflowcheck:=needoverflowcheck;
|
||||||
{ at this point, left.location.loc should be LOC_REGISTER }
|
{ at this point, left.location.loc should be LOC_REGISTER }
|
||||||
if right.location.loc=LOC_REGISTER then
|
if right.location.loc=LOC_REGISTER then
|
||||||
begin
|
begin
|
||||||
@ -152,7 +154,7 @@ unit nx86add;
|
|||||||
if (op=A_ADD) and
|
if (op=A_ADD) and
|
||||||
(right.location.loc=LOC_CONSTANT) and
|
(right.location.loc=LOC_CONSTANT) and
|
||||||
(right.location.value=1) and
|
(right.location.value=1) and
|
||||||
not(cs_check_overflow in current_settings.localswitches) and
|
not overflowcheck and
|
||||||
UseIncDec then
|
UseIncDec then
|
||||||
begin
|
begin
|
||||||
emit_reg(A_INC,TCGSize2Opsize[opsize],left.location.register);
|
emit_reg(A_INC,TCGSize2Opsize[opsize],left.location.register);
|
||||||
@ -161,7 +163,7 @@ unit nx86add;
|
|||||||
if (op=A_SUB) and
|
if (op=A_SUB) and
|
||||||
(right.location.loc=LOC_CONSTANT) and
|
(right.location.loc=LOC_CONSTANT) and
|
||||||
(right.location.value=1) and
|
(right.location.value=1) and
|
||||||
not(cs_check_overflow in current_settings.localswitches) and
|
overflowcheck and
|
||||||
UseIncDec then
|
UseIncDec then
|
||||||
begin
|
begin
|
||||||
emit_reg(A_DEC,TCGSize2Opsize[opsize],left.location.register);
|
emit_reg(A_DEC,TCGSize2Opsize[opsize],left.location.register);
|
||||||
@ -170,7 +172,7 @@ unit nx86add;
|
|||||||
if (op=A_IMUL) and
|
if (op=A_IMUL) and
|
||||||
(right.location.loc=LOC_CONSTANT) and
|
(right.location.loc=LOC_CONSTANT) and
|
||||||
(ispowerof2(int64(right.location.value),power)) and
|
(ispowerof2(int64(right.location.value),power)) and
|
||||||
not(cs_check_overflow in current_settings.localswitches) then
|
overflowcheck then
|
||||||
begin
|
begin
|
||||||
emit_const_reg(A_SHL,TCGSize2Opsize[opsize],power,left.location.register);
|
emit_const_reg(A_SHL,TCGSize2Opsize[opsize],power,left.location.register);
|
||||||
end
|
end
|
||||||
@ -178,7 +180,7 @@ unit nx86add;
|
|||||||
(right.location.loc=LOC_CONSTANT) and
|
(right.location.loc=LOC_CONSTANT) and
|
||||||
(right.location.value>1) and (ispowerof2(int64(right.location.value)-1,power)) and
|
(right.location.value>1) and (ispowerof2(int64(right.location.value)-1,power)) and
|
||||||
(power in [1..3]) and
|
(power in [1..3]) and
|
||||||
not(cs_check_overflow in current_settings.localswitches) then
|
not overflowcheck then
|
||||||
begin
|
begin
|
||||||
reference_reset_base(href,left.location.register,0,ctempposinvalid,0,[]);
|
reference_reset_base(href,left.location.register,0,ctempposinvalid,0,[]);
|
||||||
href.index:=left.location.register;
|
href.index:=left.location.register;
|
||||||
@ -209,7 +211,7 @@ unit nx86add;
|
|||||||
{ is in unsigned VAR!! }
|
{ is in unsigned VAR!! }
|
||||||
if mboverflow then
|
if mboverflow then
|
||||||
begin
|
begin
|
||||||
if cs_check_overflow in current_settings.localswitches then
|
if overflowcheck then
|
||||||
begin
|
begin
|
||||||
current_asmdata.getjumplabel(hl4);
|
current_asmdata.getjumplabel(hl4);
|
||||||
if unsigned then
|
if unsigned then
|
||||||
@ -1466,9 +1468,7 @@ unit nx86add;
|
|||||||
|
|
||||||
checkoverflow:=
|
checkoverflow:=
|
||||||
checkoverflow and
|
checkoverflow and
|
||||||
(left.resultdef.typ<>pointerdef) and
|
needoverflowcheck;
|
||||||
(right.resultdef.typ<>pointerdef) and
|
|
||||||
(cs_check_overflow in current_settings.localswitches);
|
|
||||||
|
|
||||||
opsize:=def_cgsize(left.resultdef);
|
opsize:=def_cgsize(left.resultdef);
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ interface
|
|||||||
{ filter unsigned MUL opcode, which requires special handling.
|
{ filter unsigned MUL opcode, which requires special handling.
|
||||||
Note that when overflow checking is off, we can use IMUL instead. }
|
Note that when overflow checking is off, we can use IMUL instead. }
|
||||||
if (nodetype=muln) and
|
if (nodetype=muln) and
|
||||||
(cs_check_overflow in current_settings.localswitches) and
|
needoverflowcheck and
|
||||||
(not(is_signed(left.resultdef)) or
|
(not(is_signed(left.resultdef)) or
|
||||||
not(is_signed(right.resultdef))) then
|
not(is_signed(right.resultdef))) then
|
||||||
begin
|
begin
|
||||||
@ -126,7 +126,7 @@ interface
|
|||||||
emit_ref(A_MUL,opsize,ref)
|
emit_ref(A_MUL,opsize,ref)
|
||||||
else
|
else
|
||||||
emit_reg(A_MUL,opsize,reg);
|
emit_reg(A_MUL,opsize,reg);
|
||||||
if cs_check_overflow in current_settings.localswitches then
|
if needoverflowcheck then
|
||||||
begin
|
begin
|
||||||
current_asmdata.getjumplabel(hl4);
|
current_asmdata.getjumplabel(hl4);
|
||||||
cg.a_jmp_flags(current_asmdata.CurrAsmList,F_AE,hl4);
|
cg.a_jmp_flags(current_asmdata.CurrAsmList,F_AE,hl4);
|
||||||
|
11
tests/tbs/tb0658.pp
Normal file
11
tests/tbs/tb0658.pp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{$r+,q+}
|
||||||
|
|
||||||
|
procedure test(i: int64);
|
||||||
|
begin
|
||||||
|
if (i>0) and (i<$1fff) then
|
||||||
|
halt(1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
test(0);
|
||||||
|
end.
|
Loading…
Reference in New Issue
Block a user