Procházet zdrojové kódy

+ added support for exception tags and for the 'throw' and 'catch' instructions
in the wasm internal assembler and object writer

Nikolay Nikolov před 3 roky
rodič
revize
b463f2a141

+ 4 - 2
compiler/aggas.pas

@@ -840,8 +840,6 @@ implementation
               writer.AsmWrite(gas_wasm_basic_type_str[wasm_basic_typ]);
             end;
           writer.AsmLn;
-          writer.AsmWrite(hp.tagname);
-          writer.AsmWriteLn(':');
         end;
 {$endif WASM}
 
@@ -1392,6 +1390,10 @@ implementation
                    { the dotted name is the name of the actual function entry }
                    writer.AsmWrite('.');
                  end
+               else if tai_symbol(hp).sym.typ=AT_WASM_EXCEPTION_TAG then
+                 begin
+                   { nothing here, to ensure we don' write the .type directive for exception tags }
+                 end
                else
                  begin
                    if ((target_info.system <> system_arm_linux) and (target_info.system <> system_arm_android)) or

+ 2 - 0
compiler/assemble.pas

@@ -1842,6 +1842,8 @@ Implementation
                TWasmObjData(ObjData).DeclareGlobalType(tai_globaltype(hp));
              ait_functype:
                TWasmObjData(ObjData).DeclareFuncType(tai_functype(hp));
+             ait_tagtype:
+               TWasmObjData(ObjData).DeclareTagType(tai_tagtype(hp));
              ait_export_name:
                TWasmObjData(ObjData).DeclareExportName(tai_export_name(hp));
              ait_import_module:

+ 1 - 0
compiler/ogbase.pas

@@ -118,6 +118,7 @@ interface
          RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB,
          RELOC_TYPE_INDEX_LEB,
          RELOC_GLOBAL_INDEX_LEB,
+         RELOC_TAG_INDEX_LEB,
 {$endif WASM32}
          { Relative relocation }
          RELOC_RELATIVE,

+ 129 - 3
compiler/ogwasm.pas

@@ -47,6 +47,7 @@ interface
         FuncIndex: Integer;
         SymbolIndex: Integer;
         GlobalIndex: Integer;
+        TagIndex: Integer;
         AliasOf: string;
         ExtraData: TWasmObjSymbolExtraData;
         constructor create(AList:TFPHashObjectList;const AName:string);override;
@@ -66,6 +67,7 @@ interface
 
       TWasmObjSymbolExtraData = class(TFPHashObject)
         TypeIdx: Integer;
+        ExceptionTagTypeIdx: Integer;
         ImportModule: string;
         ImportName: string;
         ExportName: string;
@@ -105,8 +107,10 @@ interface
         function AddOrCreateObjSymbolExtraData(const symname:TSymStr): TWasmObjSymbolExtraData;
         function AddFuncType(wft: TWasmFuncType): integer;
         function globalref(asmsym:TAsmSymbol):TObjSymbol;
+        function ExceptionTagRef(asmsym:TAsmSymbol):TObjSymbol;
         procedure DeclareGlobalType(gt: tai_globaltype);
         procedure DeclareFuncType(ft: tai_functype);
+        procedure DeclareTagType(tt: tai_tagtype);
         procedure DeclareExportName(en: tai_export_name);
         procedure DeclareImportModule(aim: tai_import_module);
         procedure DeclareImportName(ain: tai_import_name);
@@ -328,6 +332,7 @@ implementation
         FuncIndex:=-1;
         SymbolIndex:=-1;
         GlobalIndex:=-1;
+        TagIndex:=-1;
         AliasOf:='';
         ExtraData:=nil;
       end;
@@ -345,6 +350,7 @@ implementation
       begin
         inherited Create(HashObjectList,s);
         TypeIdx:=-1;
+        ExceptionTagTypeIdx:=-1;
       end;
 
     procedure TWasmObjSymbolExtraData.AddLocal(bastyp: TWasmBasicType);
@@ -617,6 +623,18 @@ implementation
               CurrObjSec.ObjRelocations.Add(objreloc);
               WriteUleb5(CurrObjSec,0);
             end;
+          RELOC_TAG_INDEX_LEB:
+            begin
+              if len<>5 then
+                internalerror(2021092712);
+              if Data<>0 then
+                internalerror(2021092713);
+              if not assigned(p) then
+                internalerror(2021092714);
+              objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype);
+              CurrObjSec.ObjRelocations.Add(objreloc);
+              WriteSleb5(CurrObjSec,0);
+            end;
           else
             internalerror(2021092501);
         end;
@@ -655,6 +673,19 @@ implementation
           result:=nil;
       end;
 
+    function TWasmObjData.ExceptionTagRef(asmsym: TAsmSymbol): TObjSymbol;
+      begin
+        if assigned(asmsym) then
+          begin
+            if asmsym.typ<>AT_WASM_EXCEPTION_TAG then
+              internalerror(2021092707);
+            result:=symbolref(asmsym);
+            result.typ:=AT_WASM_EXCEPTION_TAG;
+          end
+        else
+          result:=nil;
+      end;
+
     procedure TWasmObjData.DeclareGlobalType(gt: tai_globaltype);
       var
         ObjSymExtraData: TWasmObjSymbolExtraData;
@@ -675,6 +706,19 @@ implementation
         ObjSymExtraData.TypeIdx:=i;
       end;
 
+    procedure TWasmObjData.DeclareTagType(tt: tai_tagtype);
+      var
+        ObjSymExtraData: TWasmObjSymbolExtraData;
+        ft: TWasmFuncType;
+        i: Integer;
+      begin
+        ObjSymExtraData:=AddOrCreateObjSymbolExtraData(tt.tagname);
+        ft:=TWasmFuncType.Create([],tt.params);
+        i:=AddFuncType(ft);
+        ft.free;
+        ObjSymExtraData.ExceptionTagTypeIdx:=i;
+      end;
+
     procedure TWasmObjData.DeclareExportName(en: tai_export_name);
       var
         ObjSymExtraData: TWasmObjSymbolExtraData;
@@ -1022,6 +1066,13 @@ implementation
                       objsec.Data.seek(objrel.DataOffset);
                       WriteUleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).GlobalIndex);
                     end;
+                  RELOC_TAG_INDEX_LEB:
+                    begin
+                      if not assigned(objrel.symbol) then
+                        internalerror(2021092716);
+                      objsec.Data.seek(objrel.DataOffset);
+                      WriteSleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).TagIndex);
+                    end;
                   else
                     internalerror(2021092510);
                 end;
@@ -1130,6 +1181,15 @@ implementation
                       WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
                       WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
                     end;
+                  RELOC_TAG_INDEX_LEB:
+                    begin
+                      if not assigned(objrel.symbol) then
+                        internalerror(2021092717);
+                      Inc(relcount^);
+                      WriteByte(relout,Ord(R_WASM_TAG_INDEX_LEB));
+                      WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
+                      WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex);
+                    end;
                   else
                     internalerror(2021092507);
                 end;
@@ -1146,12 +1206,14 @@ implementation
         types_count,
         imports_count, NextImportFunctionIndex, NextFunctionIndex,
         section_nr, code_section_nr, data_section_nr,
-        NextGlobalIndex: Integer;
+        NextGlobalIndex, NextTagIndex: Integer;
         import_globals_count: Integer = 0;
         globals_count: Integer = 0;
         import_functions_count: Integer = 0;
         export_functions_count: Integer = 0;
         functions_count: Integer = 0;
+        import_exception_tags_count: Integer = 0;
+        exception_tags_count: Integer = 0;
         objsym, ObjSymAlias: TWasmObjSymbol;
         cust_sec: TWasmCustomSectionType;
       begin
@@ -1166,6 +1228,11 @@ implementation
         for i:=0 to Data.ObjSymbolList.Count-1 do
           begin
             objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
+            if objsym.typ=AT_WASM_EXCEPTION_TAG then
+              if objsym.bind=AB_EXTERNAL then
+                Inc(import_exception_tags_count)
+              else
+                Inc(exception_tags_count);
             if objsym.typ=AT_WASM_GLOBAL then
               if objsym.bind=AB_EXTERNAL then
                 Inc(import_globals_count)
@@ -1236,7 +1303,7 @@ implementation
               end;
           end;
 
-        imports_count:=2+import_globals_count+import_functions_count;
+        imports_count:=2+import_globals_count+import_functions_count+import_exception_tags_count;
         WriteUleb(FWasmSections[wsiImport],imports_count);
         { import memories }
         WriteName(FWasmSections[wsiImport],'env');
@@ -1293,6 +1360,26 @@ implementation
         WriteByte(FWasmSections[wsiImport],$70);  { funcref }
         WriteByte(FWasmSections[wsiImport],$00);  { min }
         WriteUleb(FWasmSections[wsiImport],1);    { 1 }
+        { import tags }
+        NextTagIndex:=0;
+        for i:=0 to Data.ObjSymbolList.Count-1 do
+          begin
+            objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
+            if (objsym.typ=AT_WASM_EXCEPTION_TAG) and (objsym.bind=AB_EXTERNAL) then
+              begin
+                objsym.TagIndex:=NextTagIndex;
+                Inc(NextTagIndex);
+                objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
+                if objsym.ExtraData.ImportModule<>'' then
+                  WriteName(FWasmSections[wsiImport],objsym.ExtraData.ImportModule)
+                else
+                  WriteName(FWasmSections[wsiImport],'env');
+                WriteName(FWasmSections[wsiImport],objsym.Name);
+                WriteByte(FWasmSections[wsiImport],$04);  { tag }
+                WriteByte(FWasmSections[wsiImport],$00);  { exception }
+                WriteUleb(FWasmSections[wsiImport],objsym.ExtraData.ExceptionTagTypeIdx);
+              end;
+          end;
 
         WriteUleb(FWasmSections[wsiFunction],functions_count);
         NextFunctionIndex:=NextImportFunctionIndex;
@@ -1307,6 +1394,23 @@ implementation
               end;
           end;
 
+        if exception_tags_count>0 then
+          begin
+            WriteUleb(FWasmSections[wsiTag],exception_tags_count);
+            for i:=0 to Data.ObjSymbolList.Count-1 do
+              begin
+                objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
+                if (objsym.typ=AT_WASM_EXCEPTION_TAG) and (objsym.bind<>AB_EXTERNAL) then
+                  begin
+                    objsym.TagIndex:=NextTagIndex;
+                    Inc(NextTagIndex);
+                    objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
+                    WriteByte(FWasmSections[wsiTag],$00);  { exception }
+                    WriteUleb(FWasmSections[wsiTag],objsym.ExtraData.ExceptionTagTypeIdx);
+                  end;
+              end;
+          end;
+
         if globals_count>0 then
           begin
             WriteUleb(FWasmSections[wsiGlobal],globals_count);
@@ -1382,7 +1486,24 @@ implementation
         for i:=0 to Data.ObjSymbolList.Count-1 do
           begin
             objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
-            if objsym.typ=AT_WASM_GLOBAL then
+            if objsym.typ=AT_WASM_EXCEPTION_TAG then
+              begin
+                objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
+                Inc(FWasmSymbolTableEntriesCount);
+                WriteByte(FWasmSymbolTable,Ord(SYMTAB_EVENT));
+                if objsym.bind=AB_GLOBAL then
+                  WriteUleb(FWasmSymbolTable,0)
+                else if objsym.bind=AB_LOCAL then
+                  WriteUleb(FWasmSymbolTable,WASM_SYM_BINDING_LOCAL)
+                else if objsym.bind=AB_EXTERNAL then
+                  WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED)
+                else
+                  internalerror(2021092715);
+                WriteUleb(FWasmSymbolTable,objsym.TagIndex);
+                if objsym.bind<>AB_EXTERNAL then
+                  WriteName(FWasmSymbolTable,objsym.Name);
+              end
+            else if objsym.typ=AT_WASM_GLOBAL then
               begin
                 objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
                 Inc(FWasmSymbolTableEntriesCount);
@@ -1488,6 +1609,11 @@ implementation
         Inc(section_nr);
         WriteWasmSection(wsiFunction);
         Inc(section_nr);
+        if exception_tags_count>0 then
+          begin
+            WriteWasmSection(wsiTag);
+            Inc(section_nr);
+          end;
         if globals_count>0 then
           begin
             WriteWasmSection(wsiGlobal);

+ 42 - 0
compiler/wasm32/aasmcpu.pas

@@ -764,6 +764,23 @@ uses
                     internalerror(2021092625);
                 end;
             end;
+          a_catch,
+          a_throw:
+            begin
+              if ops<>1 then
+                internalerror(2021092709);
+              with oper[0]^ do
+                case typ of
+                  top_ref:
+                    begin
+                      if not assigned(ref^.symbol) or (ref^.base<>NR_NO) or (ref^.index<>NR_NO) or (ref^.offset<>0) then
+                        internalerror(2021092711);
+                      result:=6;
+                    end;
+                  else
+                    internalerror(2021092710);
+                end;
+            end;
           else
             internalerror(2021092623);
         end;
@@ -1461,6 +1478,31 @@ uses
                     internalerror(2021092625);
                 end;
             end;
+          a_catch,
+          a_throw:
+            begin
+              case opcode of
+                a_catch:
+                  WriteByte($07);
+                a_throw:
+                  WriteByte($08);
+                else
+                  internalerror(2021092708);
+              end;
+              if ops<>1 then
+                internalerror(2021092709);
+              with oper[0]^ do
+                case typ of
+                  top_ref:
+                    begin
+                      if not assigned(ref^.symbol) or (ref^.base<>NR_NO) or (ref^.index<>NR_NO) or (ref^.offset<>0) then
+                        internalerror(2021092711);
+                      objdata.writeReloc(0,5,TWasmObjData(ObjData).ExceptionTagRef(ref^.symbol),RELOC_TAG_INDEX_LEB);
+                    end;
+                  else
+                    internalerror(2021092710);
+                end;
+            end;
           else
             internalerror(2021092624);
         end;

+ 5 - 2
compiler/wasm32/nwasmutil.pas

@@ -42,7 +42,7 @@ implementation
   uses
     globtype,globals,
     cpubase,
-    aasmdata,aasmcpu,
+    aasmbase,aasmdata,aasmtai,aasmcpu,
     hlcgobj,hlcgcpu,
     symdef,symtype,symconst,
     fmodule;
@@ -72,7 +72,10 @@ implementation
       list.Concat(tai_globaltype.create(STACK_POINTER_SYM,wbt_i32,false));
 
       if ts_wasm_native_exceptions in current_settings.targetswitches then
-        list.Concat(tai_tagtype.create(FPC_EXCEPTION_TAG_SYM, []));
+        begin
+          list.Concat(tai_tagtype.create(FPC_EXCEPTION_TAG_SYM, []));
+          list.Concat(tai_symbol.Create(current_asmdata.DefineAsmSymbol(FPC_EXCEPTION_TAG_SYM,AB_LOCAL,AT_WASM_EXCEPTION_TAG,nil),0));
+        end;
 
       for i:=0 to current_module.deflist.Count-1 do
         begin

+ 3 - 2
compiler/wasmbase.pas

@@ -43,7 +43,8 @@ type
     wsiElement   = 9,
     wsiCode      = 10,
     wsiData      = 11,
-    wsiDataCount = 12);
+    wsiDataCount = 12,
+    wsiTag       = 13);
 
   TWasmCustomSectionType = (
     wcstLinking,
@@ -68,7 +69,7 @@ type
     R_WASM_GLOBAL_INDEX_LEB    = 7,
     R_WASM_FUNCTION_OFFSET_I32 = 8,
     R_WASM_SECTION_OFFSET_I32  = 9,
-    R_WASM_EVENT_INDEX_LEB     = 10,
+    R_WASM_TAG_INDEX_LEB       = 10,
     R_WASM_GLOBAL_INDEX_I32    = 13,
     R_WASM_MEMORY_ADDR_LEB64   = 14,
     R_WASM_MEMORY_ADDR_SLEB64  = 15,