Browse Source

+ Wasm internal linker, object reader: implemented parsing of the type section

Nikolay Nikolov 1 year ago
parent
commit
a08c937beb
1 changed files with 122 additions and 1 deletions
  1. 122 1
      compiler/ogwasm.pas

+ 122 - 1
compiler/ogwasm.pas

@@ -184,9 +184,12 @@ interface
 
 
       TWasmObjInput = class(TObjInput)
       TWasmObjInput = class(TObjInput)
       private
       private
+        FFuncTypes: array of TWasmFuncType;
+
         function ReadUleb(r: TObjectReader; out v: uint64): boolean;
         function ReadUleb(r: TObjectReader; out v: uint64): boolean;
       public
       public
         constructor create;override;
         constructor create;override;
+        destructor Destroy;override;
         class function CanReadObjData(AReader:TObjectreader):boolean;override;
         class function CanReadObjData(AReader:TObjectreader):boolean;override;
         function ReadObjData(AReader:TObjectreader;out ObjData:TObjData):boolean;override;
         function ReadObjData(AReader:TObjectreader;out ObjData:TObjData):boolean;override;
       end;
       end;
@@ -2131,6 +2134,18 @@ implementation
         cobjdata:=TWasmObjData;
         cobjdata:=TWasmObjData;
       end;
       end;
 
 
+    destructor TWasmObjInput.Destroy;
+      var
+        i: Integer;
+      begin
+        for i:=low(FFuncTypes) to high(FFuncTypes) do
+          begin
+            FFuncTypes[i].free;
+            FFuncTypes[i]:=nil;
+          end;
+        inherited Destroy;
+      end;
+
     class function TWasmObjInput.CanReadObjData(AReader: TObjectreader): boolean;
     class function TWasmObjInput.CanReadObjData(AReader: TObjectreader): boolean;
       var
       var
         ModuleMagic: array [0..3] of Byte;
         ModuleMagic: array [0..3] of Byte;
@@ -2160,14 +2175,116 @@ implementation
           SectionSize: uint64;
           SectionSize: uint64;
           SectionStart: LongInt;
           SectionStart: LongInt;
 
 
+          TypeSectionRead: Boolean = false;
+
         function ReadCustomSection: Boolean;
         function ReadCustomSection: Boolean;
           begin
           begin
             Result:=False;
             Result:=False;
           end;
           end;
 
 
         function ReadTypeSection: Boolean;
         function ReadTypeSection: Boolean;
+          var
+            FuncTypesCount, ParamsCount, ResultsCount: uint64;
+            FuncTypeId, WasmTypeId: Byte;
+            i, j: Integer;
+            wbt: TWasmBasicType;
           begin
           begin
             Result:=False;
             Result:=False;
+            if TypeSectionRead then
+              begin
+                InputError('Type section is duplicated');
+                exit;
+              end;
+            TypeSectionRead:=True;
+            if not ReadUleb(AReader, FuncTypesCount) then
+              begin
+                InputError('Error reading the func types count');
+                exit;
+              end;
+            if AReader.Pos>(SectionStart+SectionSize) then
+              begin
+                InputError('The func types count stretches beyond the end of the type section');
+                exit;
+              end;
+            if FuncTypesCount>high(uint32) then
+              begin
+                InputError('The func types count does not fit in an unsigned 32-bit int');
+                exit;
+              end;
+            SetLength(FFuncTypes,FuncTypesCount);
+            for i:=0 to FuncTypesCount - 1 do
+              begin
+                FFuncTypes[i]:=TWasmFuncType.Create([],[]);
+                if not AReader.read(FuncTypeId,1) then
+                  begin
+                    InputError('Error reading the function type identifier');
+                    exit;
+                  end;
+                if FuncTypeId<>$60 then
+                  begin
+                    InputError('Incorrect function type identifier (expected $60, got $' + HexStr(FuncTypeId,2) + ')');
+                    exit;
+                  end;
+                if not ReadUleb(AReader, ParamsCount) then
+                  begin
+                    InputError('Error reading the function parameters count');
+                    exit;
+                  end;
+                if AReader.Pos>(SectionStart+SectionSize) then
+                  begin
+                    InputError('The function paramaters count stretches beyond the end of the type section');
+                    exit;
+                  end;
+                if ParamsCount>high(uint32) then
+                  begin
+                    InputError('The function parameters count does not fit in an unsigned 32-bit int');
+                    exit;
+                  end;
+                for j:=0 to ParamsCount-1 do
+                  begin
+                    if not AReader.read(WasmTypeId,1) then
+                      begin
+                        InputError('Error reading a function parameter basic type');
+                        exit;
+                      end;
+                    if not decode_wasm_basic_type(WasmTypeId,wbt) then
+                      begin
+                        InputError('Unknown function parameter basic type: $' + HexStr(WasmTypeId,2));
+                        exit;
+                      end;
+                    FFuncTypes[i].add_param(wbt);
+                  end;
+                if not ReadUleb(AReader, ResultsCount) then
+                  begin
+                    InputError('Error reading the function results count');
+                    exit;
+                  end;
+                if AReader.Pos>(SectionStart+SectionSize) then
+                  begin
+                    InputError('The function results count stretches beyond the end of the type section');
+                    exit;
+                  end;
+                if ResultsCount>high(uint32) then
+                  begin
+                    InputError('The function results count does not fit in an unsigned 32-bit int');
+                    exit;
+                  end;
+                for j:=0 to ResultsCount-1 do
+                  begin
+                    if not AReader.read(WasmTypeId,1) then
+                      begin
+                        InputError('Error reading a function result basic type');
+                        exit;
+                      end;
+                    if not decode_wasm_basic_type(WasmTypeId,wbt) then
+                      begin
+                        InputError('Unknown function result basic type: $' + HexStr(WasmTypeId,2));
+                        exit;
+                      end;
+                    FFuncTypes[i].add_result(wbt);
+                  end;
+              end;
+            result:=AReader.Pos=(SectionStart+SectionSize);
           end;
           end;
 
 
         function ReadImportSection: Boolean;
         function ReadImportSection: Boolean;
@@ -2233,7 +2350,11 @@ implementation
             Byte(wsiCustom):
             Byte(wsiCustom):
               Result := ReadCustomSection;
               Result := ReadCustomSection;
             Byte(wsiType):
             Byte(wsiType):
-              Result := ReadTypeSection;
+              if not ReadTypeSection then
+                begin
+                  InputError('Error reading the type section');
+                  exit;
+                end;
             Byte(wsiImport):
             Byte(wsiImport):
               Result := ReadImportSection;
               Result := ReadImportSection;
             Byte(wsiFunction):
             Byte(wsiFunction):