Răsfoiți Sursa

* WebAssembly: impose a limit on the br_table instruction length, when generating the invoke helper

Nikolay Nikolov 8 luni în urmă
părinte
comite
8790c4303a
1 a modificat fișierele cu 58 adăugiri și 9 ștergeri
  1. 58 9
      compiler/ogwasm.pas

+ 58 - 9
compiler/ogwasm.pas

@@ -5999,6 +5999,7 @@ implementation
     procedure TWasmExeOutput.GenerateCode_InvokeHelper;
       var
         Sec: TObjSection;
+        IndirectFunctionTableMap: array of Integer;
 
       procedure InvokeFuncType(typidx: Integer);
         var
@@ -6140,11 +6141,65 @@ implementation
             end;
         end;
 
+      procedure WriteBrTable(l,h: Integer; addend: Integer=0);
+        const
+          { max len of br_table instruction }
+          MaxLen=1000;
+        var
+          i, len, m: Integer;
+        begin
+          { local.get 0 }
+          Sec.writeUInt16BE($2000);
+          len:=h-l+1;
+          if len<=MaxLen then
+            begin
+              if l>0 then
+                begin
+                  { i32.const l }
+                  Sec.writeUInt8($41);
+                  WriteSleb(sec,l);
+                  { i32.sub }
+                  Sec.writeUInt8($6B);
+                end;
+              { br_table }
+              Sec.writeUInt8($0E);
+              if h=high(IndirectFunctionTableMap) then
+                begin
+                  WriteUleb(Sec,len);
+                  for i:=l to h do
+                    WriteUleb(Sec,IndirectFunctionTableMap[i]+addend);
+                  WriteUleb(Sec,addend);
+                end
+              else
+                begin
+                  WriteUleb(Sec,len-1);
+                  for i:=l to h do
+                    WriteUleb(Sec,IndirectFunctionTableMap[i]+addend);
+                end;
+            end
+          else
+            begin
+              m:=(l+h) div 2;
+              { i32.const m }
+              Sec.writeUInt8($41);
+              WriteSleb(sec,m);
+              { i32.lt_u }
+              Sec.writeUInt8($49);
+              { if }
+              Sec.writeUInt16BE($0440);
+              WriteBrTable(l,m-1,addend+1);
+              { else }
+              Sec.writeUInt8($05);
+              WriteBrTable(m,h,addend+1);
+              { end }
+              Sec.writeUInt8($0B);
+            end;
+        end;
+
       var
         exesym: TExeSymbol;
         objsym: TObjSymbol;
         i, j, TypIdx: Integer;
-        IndirectFunctionTableMap: array of Integer;
         InvokableTypeIndices: array of Integer;
       begin
         exesym:=TExeSymbol(ExeSymbolList.Find('fpc_wasm_invoke_helper'));
@@ -6186,14 +6241,8 @@ implementation
 
         { block }
         Sec.writeUInt16BE($0240);
-        { local.get 0 }
-        Sec.writeUInt16BE($2000);
-        { br_table <0, 1, 2, 3, 4, 5, 6, ..., High>, 0 }
-        Sec.writeUInt8($0E);
-        WriteUleb(Sec,Length(FIndirectFunctionTable));
-        for i:=0 to Length(FIndirectFunctionTable)-1 do
-          WriteUleb(Sec,IndirectFunctionTableMap[i]);
-        Sec.writeUInt8($00);
+        { local.get 0 + br_table }
+        WriteBrTable(low(IndirectFunctionTableMap),high(IndirectFunctionTableMap));
         { end }
         Sec.writeUInt8($0B);
         { unreachable }