From 2bce4d36db45ada7533f2e6d3d42d84d5b58b711 Mon Sep 17 00:00:00 2001 From: Nikolay Nikolov <nickysn@gmail.com> Date: Mon, 27 Sep 2021 04:24:49 +0300 Subject: [PATCH] + proper support for WASM globals in the internal object writer - emit relocations, generate a Global section, if they are declared in the object file, etc. --- compiler/ogbase.pas | 1 + compiler/ogwasm.pas | 163 +++++++++++++++++++++++++++++++++--- compiler/wasm32/aasmcpu.pas | 8 +- 3 files changed, 154 insertions(+), 18 deletions(-) diff --git a/compiler/ogbase.pas b/compiler/ogbase.pas index 2619807569..f4b4de550e 100644 --- a/compiler/ogbase.pas +++ b/compiler/ogbase.pas @@ -117,6 +117,7 @@ interface RELOC_MEMORY_ADDR_LEB, RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB, RELOC_TYPE_INDEX_LEB, + RELOC_GLOBAL_INDEX_LEB, {$endif WASM32} { Relative relocation } RELOC_RELATIVE, diff --git a/compiler/ogwasm.pas b/compiler/ogwasm.pas index 69755c6c6f..91231d7607 100644 --- a/compiler/ogwasm.pas +++ b/compiler/ogwasm.pas @@ -47,6 +47,7 @@ interface ImportIndex: Integer; FuncIndex: Integer; SymbolIndex: Integer; + GlobalIndex: Integer; AliasOf: string; ExtraData: TWasmObjSymbolExtraData; constructor create(AList:TFPHashObjectList;const AName:string);override; @@ -104,6 +105,7 @@ interface procedure writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override; function AddOrCreateObjSymbolExtraData(const symname:TSymStr): TWasmObjSymbolExtraData; function AddFuncType(wft: TWasmFuncType): integer; + function globalref(asmsym:TAsmSymbol):TObjSymbol; procedure DeclareGlobalType(gt: tai_globaltype); procedure DeclareFuncType(ft: tai_functype); procedure DeclareExportName(en: tai_export_name); @@ -327,6 +329,7 @@ implementation ImportIndex:=-1; FuncIndex:=-1; SymbolIndex:=-1; + GlobalIndex:=-1; AliasOf:=''; ExtraData:=nil; end; @@ -614,6 +617,18 @@ implementation CurrObjSec.ObjRelocations.Add(objreloc); WriteUleb5(CurrObjSec,Data); end; + RELOC_GLOBAL_INDEX_LEB: + begin + if len<>5 then + internalerror(2021092701); + if Data<>0 then + internalerror(2021092702); + if not assigned(p) then + internalerror(2021092703); + objreloc:=TWasmObjRelocation.CreateSymbol(CurrObjSec.Size,p,Reloctype); + CurrObjSec.ObjRelocations.Add(objreloc); + WriteUleb5(CurrObjSec,0); + end; else internalerror(2021092501); end; @@ -639,6 +654,19 @@ implementation FFuncTypes[result]:=TWasmFuncType.Create(wft); end; + function TWasmObjData.globalref(asmsym: TAsmSymbol): TObjSymbol; + begin + if assigned(asmsym) then + begin + if asmsym.typ<>AT_WASM_GLOBAL then + internalerror(2021092706); + result:=symbolref(asmsym); + result.typ:=AT_WASM_GLOBAL; + end + else + result:=nil; + end; + procedure TWasmObjData.DeclareGlobalType(gt: tai_globaltype); var ObjSymExtraData: TWasmObjSymbolExtraData; @@ -998,6 +1026,13 @@ implementation end; RELOC_TYPE_INDEX_LEB: ; + RELOC_GLOBAL_INDEX_LEB: + begin + if not assigned(objrel.symbol) then + internalerror(2021092509); + objsec.Data.seek(objrel.DataOffset); + WriteUleb5(objsec.Data,TWasmObjSymbol(objrel.symbol).GlobalIndex); + end; else internalerror(2021092510); end; @@ -1097,6 +1132,15 @@ implementation WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs); WriteUleb(relout,objrel.TypeIndex); end; + RELOC_GLOBAL_INDEX_LEB: + begin + if not assigned(objrel.symbol) then + internalerror(2021092704); + Inc(relcount^); + WriteByte(relout,Ord(R_WASM_GLOBAL_INDEX_LEB)); + WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs); + WriteUleb(relout,TWasmObjSymbol(objrel.symbol).SymbolIndex); + end; else internalerror(2021092507); end; @@ -1112,7 +1156,10 @@ implementation cur_seg_ofs: qword = 0; types_count, imports_count, NextImportFunctionIndex, NextFunctionIndex, - section_nr, code_section_nr, data_section_nr: Integer; + section_nr, code_section_nr, data_section_nr, + NextGlobalIndex: Integer; + import_globals_count: Integer = 0; + globals_count: Integer = 0; import_functions_count: Integer = 0; export_functions_count: Integer = 0; functions_count: Integer = 0; @@ -1130,6 +1177,11 @@ 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.bind=AB_EXTERNAL then + Inc(import_globals_count) + else + Inc(globals_count); if IsExternalFunction(objsym) then Inc(import_functions_count); if (objsym.typ=AT_FUNCTION) and not objsym.IsAlias then @@ -1192,21 +1244,35 @@ implementation end; end; - imports_count:=3+import_functions_count; + imports_count:=2+import_globals_count+import_functions_count; WriteUleb(FWasmSections[wsiImport],imports_count); - { import[0] } + { import memories } WriteName(FWasmSections[wsiImport],'env'); WriteName(FWasmSections[wsiImport],'__linear_memory'); WriteByte(FWasmSections[wsiImport],$02); { mem } WriteByte(FWasmSections[wsiImport],$00); { min } WriteUleb(FWasmSections[wsiImport],1); { 1 page } - { import[1] } - WriteName(FWasmSections[wsiImport],'env'); - WriteName(FWasmSections[wsiImport],'__stack_pointer'); - WriteByte(FWasmSections[wsiImport],$03); { global } - WriteByte(FWasmSections[wsiImport],$7F); { i32 } - WriteByte(FWasmSections[wsiImport],$01); { var } - { import[2]..import[imports_count-2] } + { import globals } + NextGlobalIndex:=0; + for i:=0 to Data.ObjSymbolList.Count-1 do + begin + objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]); + if (objsym.bind=AB_EXTERNAL) and (objsym.typ=AT_WASM_GLOBAL) then + begin + objsym.GlobalIndex:=NextGlobalIndex; + Inc(NextGlobalIndex); + 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],$03); { global } + WriteWasmBasicType(FWasmSections[wsiImport],objsym.ExtraData.GlobalType); + WriteByte(FWasmSections[wsiImport],$01); { var } + end; + end; + { import functions } NextImportFunctionIndex:=0; for i:=0 to Data.ObjSymbolList.Count-1 do begin @@ -1225,7 +1291,7 @@ implementation WriteUleb(FWasmSections[wsiImport],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).TypeIdx); end; end; - { import[imports_count-1] } + { import tables } WriteName(FWasmSections[wsiImport],'env'); WriteName(FWasmSections[wsiImport],'__indirect_function_table'); WriteByte(FWasmSections[wsiImport],$01); { table } @@ -1246,6 +1312,60 @@ implementation end; end; + if globals_count>0 then + begin + WriteUleb(FWasmSections[wsiGlobal],globals_count); + for i:=0 to Data.ObjSymbolList.Count-1 do + begin + objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]); + if (objsym.typ=AT_WASM_GLOBAL) and (objsym.bind<>AB_EXTERNAL) then + begin + objsym.GlobalIndex:=NextGlobalIndex; + Inc(NextGlobalIndex); + objsym.ExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)); + WriteWasmBasicType(FWasmSections[wsiGlobal],objsym.ExtraData.GlobalType); + WriteByte(FWasmSections[wsiGlobal],$01); { 0=const, 1=var } + { init expr } + case objsym.ExtraData.GlobalType of + wbt_i32: + begin + WriteByte(FWasmSections[wsiGlobal],$41); { i32.const } + WriteByte(FWasmSections[wsiGlobal],0); { 0 (in signed LEB128 format) } + WriteByte(FWasmSections[wsiGlobal],$0B); { end } + end; + wbt_i64: + begin + WriteByte(FWasmSections[wsiGlobal],$42); { i64.const } + WriteByte(FWasmSections[wsiGlobal],0); { 0 (in signed LEB128 format) } + WriteByte(FWasmSections[wsiGlobal],$0B); { end } + end; + wbt_f32: + begin + WriteByte(FWasmSections[wsiGlobal],$43); { f32.const } + WriteByte(FWasmSections[wsiGlobal],$00); { 0 (in little endian IEEE single precision floating point format) } + WriteByte(FWasmSections[wsiGlobal],$00); + WriteByte(FWasmSections[wsiGlobal],$00); + WriteByte(FWasmSections[wsiGlobal],$00); + WriteByte(FWasmSections[wsiGlobal],$0B); { end } + end; + wbt_f64: + begin + WriteByte(FWasmSections[wsiGlobal],$44); { f64.const } + WriteByte(FWasmSections[wsiGlobal],$00); { 0 (in little endian IEEE double precision floating point format) } + WriteByte(FWasmSections[wsiGlobal],$00); + WriteByte(FWasmSections[wsiGlobal],$00); + WriteByte(FWasmSections[wsiGlobal],$00); + WriteByte(FWasmSections[wsiGlobal],$00); + WriteByte(FWasmSections[wsiGlobal],$00); + WriteByte(FWasmSections[wsiGlobal],$00); + WriteByte(FWasmSections[wsiGlobal],$00); + WriteByte(FWasmSections[wsiGlobal],$0B); { end } + end; + end; + end; + end; + end; + if export_functions_count>0 then begin WriteUleb(FWasmSections[wsiExport],export_functions_count); @@ -1264,7 +1384,21 @@ implementation for i:=0 to Data.ObjSymbolList.Count-1 do begin objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]); - if IsExternalFunction(objsym) then + if objsym.typ=AT_WASM_GLOBAL then + begin + objsym.SymbolIndex:=FWasmSymbolTableEntriesCount; + Inc(FWasmSymbolTableEntriesCount); + WriteByte(FWasmSymbolTable,Ord(SYMTAB_GLOBAL)); + if objsym.bind=AB_EXTERNAL then + begin + WriteUleb(FWasmSymbolTable,WASM_SYM_UNDEFINED); + WriteUleb(FWasmSymbolTable,objsym.GlobalIndex); + end + else + {not implemented yet} + internalerror(2021092705); + end + else if IsExternalFunction(objsym) then begin objsym.SymbolIndex:=FWasmSymbolTableEntriesCount; Inc(FWasmSymbolTableEntriesCount); @@ -1355,6 +1489,11 @@ implementation Inc(section_nr); WriteWasmSection(wsiFunction); Inc(section_nr); + if globals_count>0 then + begin + WriteWasmSection(wsiGlobal); + Inc(section_nr); + end; if export_functions_count>0 then begin WriteWasmSection(wsiExport); diff --git a/compiler/wasm32/aasmcpu.pas b/compiler/wasm32/aasmcpu.pas index 0d43d1220c..ebaf8fc1ab 100644 --- a/compiler/wasm32/aasmcpu.pas +++ b/compiler/wasm32/aasmcpu.pas @@ -625,9 +625,7 @@ uses internalerror(2021092012); if (ref^.base<>NR_NO) or (ref^.index<>NR_NO) or (ref^.offset<>0) then internalerror(2021092013); - if ref^.symbol.Name<>'__stack_pointer' then - internalerror(2021092014); - result:=1+UlebSize(0); + result:=6; end; else internalerror(2021092011); @@ -1246,9 +1244,7 @@ uses internalerror(2021092012); if (ref^.base<>NR_NO) or (ref^.index<>NR_NO) or (ref^.offset<>0) then internalerror(2021092013); - if ref^.symbol.Name<>'__stack_pointer' then - internalerror(2021092014); - WriteUleb(0); + objdata.writeReloc(0,5,TWasmObjData(ObjData).globalref(ref^.symbol),RELOC_GLOBAL_INDEX_LEB); end; else internalerror(2021092011);