summaryrefslogtreecommitdiff
path: root/compiler/ncginl.pas
diff options
context:
space:
mode:
authorjonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2>2014-08-12 18:59:13 +0000
committerjonas <jonas@3ad0048d-3df7-0310-abae-a5850022a9f2>2014-08-12 18:59:13 +0000
commit6a10dec159b5248883759c2d9b0cedd1b7d5e392 (patch)
tree80bf56a0bb9e7a5249490dc72b577fd2139c08f0 /compiler/ncginl.pas
parent28bfadba97e134f33e5f4448705096e9648b7442 (diff)
downloadfpc-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.pas33
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));