mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-20 11:09:42 +02:00
tcgvecnode, cleanup/refactoring:
* Separated two almost identical parts of code into procedure rangecheck_string; - Removed range checking of regular_array[constant], which should, according to the comments, happen in typecheckpass. tvecnode.pass_typecheck indeed does the necessary tests, so removing this duplicate check also eliminates duplicate warning when range checking is off. git-svn-id: trunk@17124 -
This commit is contained in:
parent
7d5c4a0887
commit
cf4c00e8d6
@ -59,6 +59,7 @@ interface
|
||||
function get_mul_size : aint;
|
||||
private
|
||||
procedure rangecheck_array;
|
||||
procedure rangecheck_string;
|
||||
protected
|
||||
{# This routine is used to calculate the address of the reference.
|
||||
On entry reg contains the index in the array,
|
||||
@ -635,6 +636,10 @@ implementation
|
||||
hreg : tregister;
|
||||
paraloc1,paraloc2 : tcgpara;
|
||||
begin
|
||||
{ omit range checking when this is an array access to a pointer which has been
|
||||
typecasted from an array }
|
||||
if (ado_isconvertedpointer in tarraydef(left.resultdef).arrayoptions) then
|
||||
exit;
|
||||
paraloc1.init;
|
||||
paraloc2.init;
|
||||
if is_open_array(left.resultdef) or
|
||||
@ -690,6 +695,64 @@ implementation
|
||||
paraloc2.done;
|
||||
end;
|
||||
|
||||
procedure tcgvecnode.rangecheck_string;
|
||||
var
|
||||
paraloc1,
|
||||
paraloc2: tcgpara;
|
||||
href: treference;
|
||||
offsetdec: aint;
|
||||
begin
|
||||
paraloc1.init;
|
||||
paraloc2.init;
|
||||
case tstringdef(left.resultdef).stringtype of
|
||||
{ it's the same for ansi- and wide strings }
|
||||
st_unicodestring,
|
||||
st_widestring,
|
||||
st_ansistring:
|
||||
begin
|
||||
paramanager.getintparaloc(pocall_default,1,paraloc1);
|
||||
paramanager.getintparaloc(pocall_default,2,paraloc2);
|
||||
cg.a_load_loc_cgpara(current_asmdata.CurrAsmList,right.location,paraloc2);
|
||||
href:=location.reference;
|
||||
{ Add back the offset which was subtracted to map string[1]->pchar(string)[0] }
|
||||
{ TODO: we'd better rangecheck on the original location, before offsetting it. }
|
||||
if is_ansistring(left.resultdef) then
|
||||
offsetdec:=1
|
||||
else
|
||||
offsetdec:=2;
|
||||
if not(tf_winlikewidestring in target_info.flags) or
|
||||
(tstringdef(left.resultdef).stringtype<>st_widestring) then
|
||||
begin
|
||||
dec(href.offset,sizeof(pint)-offsetdec);
|
||||
cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_ADDR,href,paraloc1);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ winlike widestrings have a 4 byte length }
|
||||
dec(href.offset,4-offsetdec);
|
||||
cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
|
||||
end;
|
||||
paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
|
||||
paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
|
||||
cg.allocallcpuregisters(current_asmdata.CurrAsmList);
|
||||
cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resultdef).stringtypname)+'_RANGECHECK',false);
|
||||
cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
|
||||
end;
|
||||
|
||||
st_shortstring:
|
||||
begin
|
||||
{!!!!!!!!!!!!!!!!!}
|
||||
{ if this one is implemented making use of the high parameter for openshortstrings, update ncgutils.do_get_used_regvars() too (JM) }
|
||||
end;
|
||||
|
||||
st_longstring:
|
||||
begin
|
||||
{!!!!!!!!!!!!!!!!!}
|
||||
end;
|
||||
end;
|
||||
paraloc1.done;
|
||||
paraloc2.done;
|
||||
end;
|
||||
|
||||
procedure tcgvecnode.pass_generate_code;
|
||||
|
||||
@ -697,7 +760,6 @@ implementation
|
||||
offsetdec,
|
||||
extraoffset : aint;
|
||||
t : tnode;
|
||||
href : treference;
|
||||
otl,ofl : tasmlabel;
|
||||
newsize : tcgsize;
|
||||
mulsize,
|
||||
@ -828,84 +890,16 @@ implementation
|
||||
if right.nodetype=ordconstn then
|
||||
begin
|
||||
{ offset can only differ from 0 if arraydef }
|
||||
case left.resultdef.typ of
|
||||
arraydef :
|
||||
begin
|
||||
{ do not do any range checking when this is an array access to a pointer which has been
|
||||
typecasted from an array }
|
||||
if (not (ado_isconvertedpointer in tarraydef(left.resultdef).arrayoptions)) then
|
||||
begin
|
||||
if not(is_open_array(left.resultdef)) and
|
||||
not(is_array_of_const(left.resultdef)) and
|
||||
not(is_dynamic_array(left.resultdef)) then
|
||||
begin
|
||||
if (tordconstnode(right).value.svalue>tarraydef(left.resultdef).highrange) or
|
||||
(tordconstnode(right).value.svalue<tarraydef(left.resultdef).lowrange) then
|
||||
begin
|
||||
{ this should be caught in the typecheckpass! (JM) }
|
||||
if (cs_check_range in current_settings.localswitches) then
|
||||
CGMessage(parser_e_range_check_error)
|
||||
else
|
||||
CGMessage(parser_w_range_check_error);
|
||||
end;
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ range checking for open and dynamic arrays needs
|
||||
runtime code }
|
||||
secondpass(right);
|
||||
if (cs_check_range in current_settings.localswitches) then
|
||||
rangecheck_array;
|
||||
end;
|
||||
end;
|
||||
if cs_check_range in current_settings.localswitches then
|
||||
begin
|
||||
secondpass(right);
|
||||
case left.resultdef.typ of
|
||||
arraydef :
|
||||
rangecheck_array;
|
||||
stringdef :
|
||||
rangecheck_string;
|
||||
end;
|
||||
stringdef :
|
||||
begin
|
||||
if (cs_check_range in current_settings.localswitches) then
|
||||
begin
|
||||
case tstringdef(left.resultdef).stringtype of
|
||||
{ it's the same for ansi- and wide strings }
|
||||
st_unicodestring,
|
||||
st_widestring,
|
||||
st_ansistring:
|
||||
begin
|
||||
paramanager.getintparaloc(pocall_default,1,paraloc1);
|
||||
paramanager.getintparaloc(pocall_default,2,paraloc2);
|
||||
cg.a_load_const_cgpara(current_asmdata.CurrAsmList,OS_INT,tordconstnode(right).value.svalue,paraloc2);
|
||||
href:=location.reference;
|
||||
if not(tf_winlikewidestring in target_info.flags) or
|
||||
(tstringdef(left.resultdef).stringtype<>st_widestring) then
|
||||
begin
|
||||
dec(href.offset,sizeof(pint)-offsetdec);
|
||||
cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_ADDR,href,paraloc1);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ winlike widestrings have a 4 byte length }
|
||||
dec(href.offset,4-offsetdec);
|
||||
cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
|
||||
end;
|
||||
paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
|
||||
paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
|
||||
cg.allocallcpuregisters(current_asmdata.CurrAsmList);
|
||||
cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resultdef).stringtypname)+'_RANGECHECK',false);
|
||||
cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
|
||||
end;
|
||||
|
||||
st_shortstring:
|
||||
begin
|
||||
{!!!!!!!!!!!!!!!!!}
|
||||
{ if this one is implemented making use of the high parameter for openshortstrings, update ncgutils.do_get_used_regvars() too (JM) }
|
||||
end;
|
||||
|
||||
st_longstring:
|
||||
begin
|
||||
{!!!!!!!!!!!!!!!!!}
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if not(is_packed_array(left.resultdef)) or
|
||||
((mulsize mod 8 = 0) and
|
||||
(ispowerof2(mulsize div 8,temp) or
|
||||
@ -1015,56 +1009,9 @@ implementation
|
||||
if cs_check_range in current_settings.localswitches then
|
||||
begin
|
||||
if left.resultdef.typ=arraydef then
|
||||
begin
|
||||
{ do not do any range checking when this is an array access to a pointer which has been
|
||||
typecasted from an array }
|
||||
if (not (ado_isconvertedpointer in tarraydef(left.resultdef).arrayoptions)) then
|
||||
rangecheck_array
|
||||
end
|
||||
rangecheck_array
|
||||
else if (left.resultdef.typ=stringdef) then
|
||||
begin
|
||||
case tstringdef(left.resultdef).stringtype of
|
||||
{ it's the same for ansi- and wide strings }
|
||||
st_unicodestring,
|
||||
st_widestring,
|
||||
st_ansistring:
|
||||
begin
|
||||
paramanager.getintparaloc(pocall_default,1,paraloc1);
|
||||
paramanager.getintparaloc(pocall_default,2,paraloc2);
|
||||
cg.a_load_reg_cgpara(current_asmdata.CurrAsmList,OS_INT,right.location.register,paraloc2);
|
||||
href:=location.reference;
|
||||
dec(href.offset,sizeof(pint)-offsetdec);
|
||||
|
||||
href:=location.reference;
|
||||
if not(tf_winlikewidestring in target_info.flags) or
|
||||
(tstringdef(left.resultdef).stringtype<>st_widestring) then
|
||||
begin
|
||||
dec(href.offset,sizeof(pint)-offsetdec);
|
||||
cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_ADDR,href,paraloc1);
|
||||
end
|
||||
else
|
||||
begin
|
||||
{ winlike widestrings have a 4 byte length }
|
||||
dec(href.offset,4-offsetdec);
|
||||
cg.a_load_ref_cgpara(current_asmdata.CurrAsmList,OS_32,href,paraloc1);
|
||||
end;
|
||||
|
||||
paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc1);
|
||||
paramanager.freecgpara(current_asmdata.CurrAsmList,paraloc2);
|
||||
cg.allocallcpuregisters(current_asmdata.CurrAsmList);
|
||||
cg.a_call_name(current_asmdata.CurrAsmList,'FPC_'+upper(tstringdef(left.resultdef).stringtypname)+'_RANGECHECK',false);
|
||||
cg.deallocallcpuregisters(current_asmdata.CurrAsmList);
|
||||
end;
|
||||
st_shortstring:
|
||||
begin
|
||||
{!!!!!!!!!!!!!!!!!}
|
||||
end;
|
||||
st_longstring:
|
||||
begin
|
||||
{!!!!!!!!!!!!!!!!!}
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
rangecheck_string;
|
||||
end;
|
||||
|
||||
{ insert the register and the multiplication factor in the
|
||||
|
Loading…
Reference in New Issue
Block a user