浏览代码

+ inline high(<dyn. array>), resolves #28536

git-svn-id: trunk@43808 -
florian 5 年之前
父节点
当前提交
f7a052f884
共有 3 个文件被更改,包括 94 次插入17 次删除
  1. 39 0
      compiler/ncginl.pas
  2. 19 17
      compiler/ninl.pas
  3. 36 0
      compiler/x86/nx86inl.pas

+ 39 - 0
compiler/ncginl.pas

@@ -66,6 +66,7 @@ interface
           procedure second_seg; virtual; abstract;
           procedure second_fma; virtual;
           procedure second_frac_real; virtual;
+          procedure second_high; virtual;
        protected
           function  second_incdec_tempregdef: tdef;virtual;
        end;
@@ -226,6 +227,8 @@ implementation
             in_neg_assign_x,
             in_not_assign_x:
                second_NegNot_assign;
+            in_high_x:
+              second_high;
             else
                pass_generate_code_cpu;
          end;
@@ -303,6 +306,42 @@ implementation
          end;
       end;
 
+{*****************************************************************************
+                          HIGH(<dyn. array>) GENERIC HANDLING
+*****************************************************************************}
+
+    procedure tcginlinenode.second_high;
+      var
+        loadlab, nillab, donelab: tasmlabel;
+        hregister : tregister;
+        href : treference;
+      begin
+        secondpass(left);
+        if not(is_dynamic_array(left.resultdef)) then
+          Internalerror(2019122801);
+        { length 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(loadlab);
+        current_asmdata.getjumplabel(nillab);
+        current_asmdata.getjumplabel(donelab);
+        hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,left.resultdef,OC_EQ,0,left.location.register,nillab);
+        { volatility of the dyn. array refers to the volatility of the
+          string pointer, not of the string data }
+        hlcg.reference_reset_base(href,left.resultdef,left.location.register,-ossinttype.size,ctempposinvalid,ossinttype.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,ossinttype,resultdef,href,hregister);
+        hlcg.a_jmp_always(current_asmdata.CurrAsmList,donelab);
+
+        cg.a_label(current_asmdata.CurrAsmList,nillab);
+        hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,resultdef,1,hregister);
+        cg.a_label(current_asmdata.CurrAsmList,donelab);
+        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+        location.register:=hregister;
+      end;
+
 
 {*****************************************************************************
                          PRED/SUCC GENERIC HANDLING

+ 19 - 17
compiler/ninl.pas

@@ -85,6 +85,7 @@ interface
             by the JVM backend to create new dynamic arrays. }
           function first_new: tnode; virtual;
           function first_length: tnode; virtual;
+          function first_high: tnode; virtual;
           function first_box: tnode; virtual; abstract;
           function first_unbox: tnode; virtual; abstract;
           function first_assigned: tnode; virtual;
@@ -3484,21 +3485,10 @@ implementation
                               result:=load_high_value_node(tparavarsym(tloadnode(left).symtableentry));
                             end
                            else
-                            if is_dynamic_array(left.resultdef) then
-                              begin
-                                set_varstate(left,vs_read,[vsf_must_be_valid]);
-                                { can't use inserttypeconv because we need }
-                                { an explicit type conversion (JM)         }
-                                hp := ccallparanode.create(ctypeconvnode.create_internal(left,voidpointertype),nil);
-                                result := ccallnode.createintern('fpc_dynarray_high',hp);
-                                { make sure the left node doesn't get disposed, since it's }
-                                { reused in the new node (JM)                              }
-                                left:=nil;
-                              end
-                           else
-                            begin
-                              set_varstate(left,vs_read,[]);
-                            end;
+                             begin
+                               set_varstate(left,vs_read,[]);
+                               resultdef:=sizesinttype;
+                             end;
                          end;
                       end;
                     stringdef:
@@ -4047,9 +4037,12 @@ implementation
               result:=first_assert;
             end;
 
-          in_low_x,
-          in_high_x:
+          in_low_x:
             internalerror(200104047);
+          in_high_x:
+            begin
+              result:=first_high;
+            end;
 
           in_slice_x:
             internalerror(2005101501);
@@ -4705,6 +4698,15 @@ implementation
        end;
 
 
+     function tinlinenode.first_high: tnode;
+       begin
+         result:=nil;
+         if not(is_dynamic_array(left.resultdef)) then
+           Internalerror(2019122802);
+         expectloc:=LOC_REGISTER;
+       end;
+
+
      function tinlinenode.first_assigned: tnode;
        begin
          { Comparison must not call procvars, indicate that with nf_load_procvar flag }

+ 36 - 0
compiler/x86/nx86inl.pas

@@ -78,6 +78,7 @@ interface
           procedure second_fma;override;
           procedure second_frac_real;override;
           procedure second_int_real;override;
+          procedure second_high;override;
        private
           procedure load_fpu_location(lnode: tnode);
        end;
@@ -1271,4 +1272,39 @@ implementation
           internalerror(2017052107);
       end;
 
+
+    procedure tx86inlinenode.second_high;
+      var
+        donelab: tasmlabel;
+        hregister : tregister;
+        href : treference;
+      begin
+        secondpass(left);
+        if not(is_dynamic_array(left.resultdef)) then
+          Internalerror(2019122801);
+        { length 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(donelab);
+        { by subtracting 1 here, we get the -1 into the register we need if the dyn. array is nil and the carry
+          flag is set in this case, so we can jump depending on it
+
+          when loading the actual high value, we have to take care later of the decreased value }
+        hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SUB,left.resultdef,1,left.location.register);
+        { volatility of the dyn. array refers to the volatility of the
+          string pointer, not of the string data }
+        cg.a_jmp_flags(current_asmdata.CurrAsmList,F_C,donelab);
+        hlcg.reference_reset_base(href,left.resultdef,left.location.register,-ossinttype.size+1,ctempposinvalid,ossinttype.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,ossinttype,resultdef,href,hregister);
+
+        cg.a_label(current_asmdata.CurrAsmList,donelab);
+        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+        location.register:=hregister;
+      end;
+
+
+
 end.