diff options
author | jonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2014-08-12 18:59:13 +0000 |
---|---|---|
committer | jonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2> | 2014-08-12 18:59:13 +0000 |
commit | 6a10dec159b5248883759c2d9b0cedd1b7d5e392 (patch) | |
tree | 80bf56a0bb9e7a5249490dc72b577fd2139c08f0 /compiler/ncginl.pas | |
parent | 28bfadba97e134f33e5f4448705096e9648b7442 (diff) | |
download | fpc-6a10dec159b5248883759c2d9b0cedd1b7d5e392.tar.gz |
* fixed the resultdef of length() intrinsic: it's ossinttype rather than
sinttype (they're the same on most platforms, except on 8 bit ones where
ossinttype is still 16 bit)
* simplified and documented second_length(), and fixed some (harmless)
errors in the used tcgsize for the resultdef (it had to be OS_SINT
rather than OS_INT -- now it's just def_cgsize(resultdef) so it's
always correct)
git-svn-id: http://svn.freepascal.org/svn/fpc/branches/hlcgllvm@28387 3ad0048d-3df7-0310-abae-a5850022a9f2
Diffstat (limited to 'compiler/ncginl.pas')
-rw-r--r-- | compiler/ncginl.pas | 33 |
1 files changed, 19 insertions, 14 deletions
diff --git a/compiler/ncginl.pas b/compiler/ncginl.pas index d6348d324d..8be0208ffb 100644 --- a/compiler/ncginl.pas +++ b/compiler/ncginl.pas @@ -68,7 +68,7 @@ implementation uses globtype,systems,constexp, cutils,verbose,globals, - symconst,symdef,defutil,symsym, + symconst,symtype,symdef,defutil,symsym, aasmbase,aasmtai,aasmdata,aasmcpu,parabase, cgbase,pass_1,pass_2, cpuinfo,cpubase,paramgr,procinfo, @@ -287,6 +287,7 @@ implementation var lengthlab : tasmlabel; hregister : tregister; + lendef : tdef; href : treference; begin secondpass(left); @@ -301,24 +302,28 @@ implementation hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false); current_asmdata.getjumplabel(lengthlab); hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,left.resultdef,OC_EQ,0,left.location.register,lengthlab); - if is_widestring(left.resultdef) and (tf_winlikewidestring in target_info.flags) then - begin - hlcg.reference_reset_base(href,left.resultdef,left.location.register,-sizeof(dword),sizeof(dword)); - hregister:=cg.makeregsize(current_asmdata.CurrAsmList,left.location.register,OS_INT); - cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_32,OS_INT,href,hregister); - end + { the length of a widestring is a 32 bit unsigned int. Since every + character occupies 2 bytes, on a 32 bit platform you can express + the maximum length using 31 bits. On a 64 bit platform, it may be + 32 bits. This means that regardless of the platform, a location + with size OS_SINT/ossinttype can hold the length without + overflowing (this code returns an ossinttype value) } + if is_widestring(left.resultdef) then + lendef:=u32inttype else - begin - hlcg.reference_reset_base(href,left.resultdef,left.location.register,-sizeof(pint),sizeof(pint)); - hregister:=cg.makeregsize(current_asmdata.CurrAsmList,left.location.register,OS_INT); - cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_INT,OS_INT,href,hregister); - end; + lendef:=ossinttype; + hlcg.reference_reset_base(href,left.resultdef,left.location.register,-lendef.size,lendef.alignment); + { if the string pointer is nil, the length is 0 -> reuse the register + that originally held the string pointer for the length, so that we + can keep the original nil/0 as length in that case } + hregister:=cg.makeregsize(current_asmdata.CurrAsmList,left.location.register,def_cgsize(resultdef)); + hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,lendef,resultdef,href,hregister); if is_widestring(left.resultdef) then - cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHR,OS_INT,1,hregister); + hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHR,resultdef,1,hregister); { Dynamic arrays do not have their length attached but their maximum index } if is_dynamic_array(left.resultdef) then - cg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,OS_INT,1,hregister); + hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,resultdef,1,hregister); cg.a_label(current_asmdata.CurrAsmList,lengthlab); location_reset(location,LOC_REGISTER,def_cgsize(resultdef)); |