2
0
Эх сурвалжийг харах

+ implemented length() code generation for WebAssembly

git-svn-id: branches/wasm@48198 -
nickysn 4 жил өмнө
parent
commit
cc94ab3ab8

+ 2 - 0
compiler/wasm32/hlcgcpu.pas

@@ -213,6 +213,7 @@ uses
 
       function g_call_system_proc_intern(list: TAsmList; pd: tprocdef; const paras: array of pcgpara; forceresdef: tdef): tcgpara; override;
 
+     public
       { in case of an array, the array base address and index have to be
         put on the evaluation stack before the stored value; similarly, for
         fields the self pointer has to be loaded first. Also checks whether
@@ -220,6 +221,7 @@ uses
         twice. Returns how many stack slots have been consumed, disregarding
         the "dup". }
       function prepare_stack_for_ref(list: TAsmList; var ref: treference; dup: boolean): longint;
+     protected
       { return the load/store opcode to load/store from/to ref; if the result
         has to be and'ed after a load to get the final value, that constant
         is returned in finishandval (otherwise that value is set to -1) }

+ 74 - 1
compiler/wasm32/nwasminl.pas

@@ -33,12 +33,85 @@ interface
       { twasminlinenode }
 
       twasminlinenode = class(tcginlinenode)
+      public
+        procedure second_length;override;
       end;
 
 implementation
 
     uses
-      ninl;
+      ninl,
+      cpubase,
+      aasmbase,aasmdata,aasmcpu,
+      cgbase,cgutils,
+      hlcgobj,hlcgcpu,
+      defutil,pass_2,
+      symtype,symdef;
+
+{*****************************************************************************
+                               twasminlinenode
+*****************************************************************************}
+
+    procedure twasminlinenode.second_length;
+      var
+        lendef : tdef;
+        href : treference;
+        extra_slots: LongInt;
+      begin
+        secondpass(left);
+        if is_shortstring(left.resultdef) then
+          begin
+            location_copy(location,left.location);
+            location.size:=OS_8;
+          end
+        else
+          begin
+            { 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);
+
+            thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,left.resultdef,OC_EQ,0,left.location.register);
+
+            current_asmdata.CurrAsmList.Concat(taicpu.op_functype(a_if,TWasmFuncType.Create([],[wbt_i32])));
+            thlcgwasm(hlcg).incblock;
+            thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
+
+            current_asmdata.CurrAsmList.Concat(taicpu.op_const(a_i32_const,0));
+            thlcgwasm(hlcg).incstack(current_asmdata.CurrAsmList,1);
+
+            current_asmdata.CurrAsmList.Concat( taicpu.op_none(a_else) );
+            thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);
+
+            { 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,[]);
+
+            extra_slots:=thlcgwasm(hlcg).prepare_stack_for_ref(current_asmdata.CurrAsmList,href,false);
+            thlcgwasm(hlcg).a_load_ref_stack(current_asmdata.CurrAsmList,lendef,href,extra_slots);
+            if is_widestring(left.resultdef) then
+              thlcgwasm(hlcg).a_op_const_stack(current_asmdata.CurrAsmList,OP_SHR,resultdef,1);
+
+            { Dynamic arrays do not have their length attached but their maximum index }
+            if is_dynamic_array(left.resultdef) then
+              thlcgwasm(hlcg).a_op_const_stack(current_asmdata.CurrAsmList,OP_ADD,resultdef,1);
+
+            current_asmdata.CurrAsmList.Concat( taicpu.op_none(a_end_if) );
+            thlcgwasm(hlcg).decblock;
+
+            location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
+            location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);
+            thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);
+          end;
+      end;
 
 begin
   cinlinenode:=twasminlinenode;