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