Browse Source

m68k: have an arch-specific second_length implementation, to make sure length() doesn't return its result in an address register

git-svn-id: trunk@45201 -
Károly Balogh 5 years ago
parent
commit
89d9679b53
1 changed files with 56 additions and 1 deletions
  1. 56 1
      compiler/m68k/n68kinl.pas

+ 56 - 1
compiler/m68k/n68kinl.pas

@@ -42,6 +42,7 @@ interface
         function first_round_real: tnode; override;
         function first_trunc_real: tnode; override;
 
+        procedure second_length; override;
         procedure second_abs_real; override;
         procedure second_sqr_real; override;
         procedure second_sqrt_real; override;
@@ -66,7 +67,7 @@ implementation
 
     uses
       globtype,verbose,globals,cutils,
-      cpuinfo,defutil,symdef,aasmdata,aasmcpu,aasmtai,
+      cpuinfo,defutil,symdef,aasmbase,aasmdata,aasmcpu,aasmtai,
       cgbase,cgutils,pass_1,pass_2,symconst,
       ncnv,ncgutil,cgobj,cgcpu,hlcgobj;
 
@@ -74,6 +75,60 @@ implementation
                               t68kinlinenode
 *****************************************************************************}
 
+    procedure t68kinlinenode.second_Length;
+      var
+        lengthlab,zerolab : tasmlabel;
+        hregister : tregister;
+        lendef : tdef;
+        href : treference;
+      begin
+        secondpass(left);
+        if is_shortstring(left.resultdef) then
+         begin
+           location_copy(location,left.location);
+           location.size:=OS_8;
+         end
+        else
+         begin
+           //current_asmdata.CurrAsmList.concat(tai_comment.create(strpnew('second_length called!')));
+
+           { length in ansi/wide strings and high in dynamic arrays is at offset -sizeof(pint) }
+           hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);
+           current_asmdata.getjumplabel(zerolab);
+           hregister:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);
+           hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,left.resultdef,OC_EQ,0,left.location.register,zerolab);
+           { 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
+             lendef:=ossinttype;
+           { volatility of the ansistring/widestring refers to the volatility of the
+             string pointer, not of the string data }
+           hlcg.reference_reset_base(href,left.resultdef,left.location.register,-lendef.size,ctempposinvalid,lendef.alignment,[]);
+           hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,lendef,resultdef,href,hregister);
+           if is_widestring(left.resultdef) then
+             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
+             hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,resultdef,1,hregister);
+           current_asmdata.getjumplabel(lengthlab);
+           hlcg.a_jmp_always(current_asmdata.CurrAsmlist,lengthlab);
+
+           cg.a_label(current_asmdata.CurrAsmList,zerolab);
+           hlcg.a_load_const_reg(current_asmdata.CurrAsmList,resultdef,0,hregister);
+
+           cg.a_label(current_asmdata.CurrAsmList,lengthlab);
+           location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+           location.register:=hregister;
+         end;
+      end;
+
     function t68kinlinenode.first_abs_real : tnode;
       begin
         if FPUM68K_HAS_HARDWARE in fpu_capabilities[current_settings.fputype] then