فهرست منبع

+ perform WebAssembly validation, if the compiler is compiled with the
DEBUG_WASM_VALIDATION defined

Nikolay Nikolov 1 سال پیش
والد
کامیت
f2d739b93a
2فایلهای تغییر یافته به همراه58 افزوده شده و 4 حذف شده
  1. 17 3
      compiler/wasm32/aasmcpu.pas
  2. 41 1
      compiler/wasm32/cpupi.pas

+ 17 - 3
compiler/wasm32/aasmcpu.pas

@@ -108,8 +108,10 @@ uses
         FValueStack: TWasmValueStack;
         FCtrlStack: TWasmControlStack;
         FGetLocalType: TGetLocalTypeProc;
+        FFuncType: TWasmFuncType;
+        FEndFunctionReached: Boolean;
       public
-        constructor Create(AGetLocalType: TGetLocalTypeProc);
+        constructor Create(AGetLocalType: TGetLocalTypeProc; AFuncType: TWasmFuncType);
         destructor Destroy; override;
 
         procedure PushVal(vt: TWasmBasicType);
@@ -500,11 +502,14 @@ uses
 
     { TWasmValidationStacks }
 
-    constructor TWasmValidationStacks.Create(AGetLocalType: TGetLocalTypeProc);
+    constructor TWasmValidationStacks.Create(AGetLocalType: TGetLocalTypeProc; AFuncType: TWasmFuncType);
       begin
+        FEndFunctionReached:=False;
         FGetLocalType:=AGetLocalType;
         FValueStack:=TWasmValueStack.Create;
         FCtrlStack:=TWasmControlStack.Create;
+        FFuncType:=AFuncType;
+        PushCtrl(a_block,[],[]);
       end;
 
     destructor TWasmValidationStacks.Destroy;
@@ -534,7 +539,7 @@ uses
     function TWasmValidationStacks.PopVal(expect: TWasmBasicType): TWasmBasicType;
       begin
         Result:=wbt_Unknown;
-        Result:=PopVal;
+        Result:=PopVal();
         if (Result<>expect) and (Result<>wbt_Unknown) and (expect<>wbt_Unknown) then
           internalerror(2024013105);
       end;
@@ -643,6 +648,8 @@ uses
         frame: TWasmControlFrame;
         n: TCGInt;
       begin
+        if FEndFunctionReached then
+          internalerror(2024022602);
         case a.opcode of
           a_nop:
             ;
@@ -1110,6 +1117,13 @@ uses
               PopVals(label_types(FCtrlStack[n]));
               PushVals(label_types(FCtrlStack[n]));
             end;
+          a_return:
+            begin
+              PopVals(FFuncType.results);
+              Unreachable;
+            end;
+          a_end_function:
+            FEndFunctionReached:=True;
           else
             internalerror(2024030502);
         end;

+ 41 - 1
compiler/wasm32/cpupi.pas

@@ -36,6 +36,9 @@ interface
 
     tcpuprocinfo=class(tcgprocinfo)
     private
+      FFuncType: TWasmFuncType;
+      FLocals: array of TWasmBasicType;
+      FParametersCount: Integer;
       FFirstFreeLocal: Integer;
       FAllocatedLocals: array of TWasmBasicType;
       FGotoTargets: TFPHashObjectList;
@@ -47,6 +50,7 @@ interface
 
       { used for allocating locals during the postprocess_code stage (i.e. after register allocation) }
       function AllocWasmLocal(wbt: TWasmBasicType): Integer;
+      function GetLocalType(localidx: Integer): TWasmBasicType;
     public
       { label to the nearest local exception handler }
       CurrRaiseLabel : tasmlabel;
@@ -423,6 +427,16 @@ implementation
         SetLength(FAllocatedLocals,Length(FAllocatedLocals)+1);
         FAllocatedLocals[High(FAllocatedLocals)]:=wbt;
         result:=High(FAllocatedLocals)+FFirstFreeLocal;
+
+        SetLength(FLocals,Length(FLocals)+1);
+        FLocals[High(FLocals)]:=wbt;
+      end;
+
+    function tcpuprocinfo.GetLocalType(localidx: Integer): TWasmBasicType;
+      begin
+        if (localidx<Low(FLocals)) or (localidx>High(FLocals)) then
+          internalerror(2024022601);
+        result:=FLocals[localidx];
       end;
 
     constructor tcpuprocinfo.create(aparent: tprocinfo);
@@ -889,9 +903,14 @@ implementation
             local:=nil;
             first:=true;
             l:=ttgwasm(tg).localvars.first;
-            FFirstFreeLocal:=Length(findfirst_tai_functype(aktproccode).functype.params);
+            FFuncType:=findfirst_tai_functype(aktproccode).functype;
+            FLocals:=Copy(FFuncType.params);
+            FParametersCount:=Length(FLocals);
+            FFirstFreeLocal:=FParametersCount;
             while Assigned(l) do
               begin
+                SetLength(FLocals,Length(FLocals)+1);
+                FLocals[High(FLocals)]:=l.typ;
                 local:=tai_local.create(l.typ);
                 local.first:=first;
                 first:=false;
@@ -944,6 +963,23 @@ implementation
               end;
           end;
 
+        procedure validate_code;
+          var
+            vs: TWasmValidationStacks;
+            hp: tai;
+          begin
+            vs:=TWasmValidationStacks.Create(@GetLocalType,FFuncType);
+
+            hp:=tai(aktproccode.first);
+            while assigned(hp) do
+              begin
+                if hp.typ=ait_instruction then
+                  vs.Validate(taicpu(hp));
+                hp:=tai(hp.next);
+              end;
+            vs.Free;
+          end;
+
       var
         localslist: TAsmList;
         labels_resolved, has_goto: Boolean;
@@ -967,6 +1003,10 @@ implementation
         insert_localslist(aktproccode,localslist);
         localslist.Free;
 
+{$ifdef DEBUG_WASM_VALIDATION}
+        validate_code;
+{$endif DEBUG_WASM_VALIDATION}
+
         inherited postprocess_code;
       end;