Browse Source

+ workaround for WebAssembly treating the stack parameter of the store and load
instructions as unsigned. This caused an 'out of bounds memory access' trap
when accessing arrays with negative offset index, e.g. in test/cg/tvec.pp

Nikolay Nikolov 3 years ago
parent
commit
5adec3ca98
1 changed files with 60 additions and 4 deletions
  1. 60 4
      compiler/wasm32/hlcgcpu.pas

+ 60 - 4
compiler/wasm32/hlcgcpu.pas

@@ -1072,12 +1072,26 @@ implementation
           incstack(list,1);
           list.Concat(taicpu.op_none(a_i32_add));
           decstack(list,1);
+          if assigned(ref.symbol) then
+            begin
+              list.Concat(taicpu.op_sym(a_i32_const,ref.symbol));
+              incstack(list,1);
+              list.Concat(taicpu.op_none(a_i32_add));
+              decstack(list,1);
+            end;
           if ref.offset<0 then
             begin
               list.Concat(taicpu.op_const(a_i32_const,-ref.offset));
               incstack(list,1);
               list.Concat(taicpu.op_none(a_i32_sub));
               decstack(list,1);
+            end
+          else if ref.offset>0 then
+            begin
+              list.Concat(taicpu.op_const(a_i32_const,ref.offset));
+              incstack(list,1);
+              list.Concat(taicpu.op_none(a_i32_add));
+              decstack(list,1);
             end;
           if dup then
             begin
@@ -1087,18 +1101,32 @@ implementation
               incstack(list,1);
               list.Concat(taicpu.op_none(a_i32_add));
               decstack(list,1);
+              if assigned(ref.symbol) then
+                begin
+                  list.Concat(taicpu.op_sym(a_i32_const,ref.symbol));
+                  incstack(list,1);
+                  list.Concat(taicpu.op_none(a_i32_add));
+                  decstack(list,1);
+                end;
               if ref.offset<0 then
                 begin
                   list.Concat(taicpu.op_const(a_i32_const,-ref.offset));
                   incstack(list,1);
                   list.Concat(taicpu.op_none(a_i32_sub));
                   decstack(list,1);
+                end
+              else if ref.offset>0 then
+                begin
+                  list.Concat(taicpu.op_const(a_i32_const,ref.offset));
+                  incstack(list,1);
+                  list.Concat(taicpu.op_none(a_i32_add));
+                  decstack(list,1);
                 end;
             end;
           ref.base:=NR_NO;
           ref.index:=NR_NO;
-          if ref.offset<0 then
-            ref.offset:=0;
+          ref.offset:=0;
+          ref.symbol:=nil;
           result:=1;
         end
       else if (ref.base<>NR_NO) then
@@ -1107,26 +1135,54 @@ implementation
             begin
               { regular field -> load self on the stack }
               a_load_reg_stack(list,voidpointertype,ref.base);
+              if assigned(ref.symbol) then
+                begin
+                  list.Concat(taicpu.op_sym(a_i32_const,ref.symbol));
+                  incstack(list,1);
+                  list.Concat(taicpu.op_none(a_i32_add));
+                  decstack(list,1);
+                end;
               if ref.offset<0 then
                 begin
                   list.Concat(taicpu.op_const(a_i32_const,-ref.offset));
                   incstack(list,1);
                   list.Concat(taicpu.op_none(a_i32_sub));
                   decstack(list,1);
+                end
+              else if ref.offset>0 then
+                begin
+                  list.Concat(taicpu.op_const(a_i32_const,ref.offset));
+                  incstack(list,1);
+                  list.Concat(taicpu.op_none(a_i32_add));
+                  decstack(list,1);
                 end;
               if dup then
                 begin
                   a_load_reg_stack(list,voidpointertype,ref.base);
+                  if assigned(ref.symbol) then
+                    begin
+                      list.Concat(taicpu.op_sym(a_i32_const,ref.symbol));
+                      incstack(list,1);
+                      list.Concat(taicpu.op_none(a_i32_add));
+                      decstack(list,1);
+                    end;
                   if ref.offset<0 then
                     begin
                       list.Concat(taicpu.op_const(a_i32_const,-ref.offset));
                       incstack(list,1);
                       list.Concat(taicpu.op_none(a_i32_sub));
                       decstack(list,1);
+                    end
+                  else if ref.offset>0 then
+                    begin
+                      list.Concat(taicpu.op_const(a_i32_const,ref.offset));
+                      incstack(list,1);
+                      list.Concat(taicpu.op_none(a_i32_add));
+                      decstack(list,1);
                     end;
                 end;
-              if ref.offset<0 then
-                ref.offset:=0;
+              ref.offset:=0;
+              ref.symbol:=nil;
               ref.base:=NR_NO;
               result:=1;
             end