diff --git a/compiler/aggas.pas b/compiler/aggas.pas index 894ef329f4..d25f12ae7b 100644 --- a/compiler/aggas.pas +++ b/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 diff --git a/compiler/assemble.pas b/compiler/assemble.pas index 68b8f02f20..08a1818f4d 100644 --- a/compiler/assemble.pas +++ b/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: diff --git a/compiler/ogbase.pas b/compiler/ogbase.pas index f4b4de550e..ab627e663e 100644 --- a/compiler/ogbase.pas +++ b/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, diff --git a/compiler/ogwasm.pas b/compiler/ogwasm.pas index 79e2ec0884..2cf3bfb05e 100644 --- a/compiler/ogwasm.pas +++ b/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); diff --git a/compiler/wasm32/aasmcpu.pas b/compiler/wasm32/aasmcpu.pas index 0c3fad0a35..e6ee9f6dfc 100644 --- a/compiler/wasm32/aasmcpu.pas +++ b/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; diff --git a/compiler/wasm32/nwasmutil.pas b/compiler/wasm32/nwasmutil.pas index 2f68dffe72..d7f854661d 100644 --- a/compiler/wasm32/nwasmutil.pas +++ b/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 diff --git a/compiler/wasmbase.pas b/compiler/wasmbase.pas index 60ca30869e..c2e4863269 100644 --- a/compiler/wasmbase.pas +++ b/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,