mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-28 15:00:29 +02:00
+ 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.
This commit is contained in:
parent
5ad2d47e23
commit
2bce4d36db
@ -117,6 +117,7 @@ interface
|
|||||||
RELOC_MEMORY_ADDR_LEB,
|
RELOC_MEMORY_ADDR_LEB,
|
||||||
RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB,
|
RELOC_MEMORY_ADDR_OR_TABLE_INDEX_SLEB,
|
||||||
RELOC_TYPE_INDEX_LEB,
|
RELOC_TYPE_INDEX_LEB,
|
||||||
|
RELOC_GLOBAL_INDEX_LEB,
|
||||||
{$endif WASM32}
|
{$endif WASM32}
|
||||||
{ Relative relocation }
|
{ Relative relocation }
|
||||||
RELOC_RELATIVE,
|
RELOC_RELATIVE,
|
||||||
|
@ -47,6 +47,7 @@ interface
|
|||||||
ImportIndex: Integer;
|
ImportIndex: Integer;
|
||||||
FuncIndex: Integer;
|
FuncIndex: Integer;
|
||||||
SymbolIndex: Integer;
|
SymbolIndex: Integer;
|
||||||
|
GlobalIndex: Integer;
|
||||||
AliasOf: string;
|
AliasOf: string;
|
||||||
ExtraData: TWasmObjSymbolExtraData;
|
ExtraData: TWasmObjSymbolExtraData;
|
||||||
constructor create(AList:TFPHashObjectList;const AName:string);override;
|
constructor create(AList:TFPHashObjectList;const AName:string);override;
|
||||||
@ -104,6 +105,7 @@ interface
|
|||||||
procedure writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override;
|
procedure writeReloc(Data:TRelocDataInt;len:aword;p:TObjSymbol;Reloctype:TObjRelocationType);override;
|
||||||
function AddOrCreateObjSymbolExtraData(const symname:TSymStr): TWasmObjSymbolExtraData;
|
function AddOrCreateObjSymbolExtraData(const symname:TSymStr): TWasmObjSymbolExtraData;
|
||||||
function AddFuncType(wft: TWasmFuncType): integer;
|
function AddFuncType(wft: TWasmFuncType): integer;
|
||||||
|
function globalref(asmsym:TAsmSymbol):TObjSymbol;
|
||||||
procedure DeclareGlobalType(gt: tai_globaltype);
|
procedure DeclareGlobalType(gt: tai_globaltype);
|
||||||
procedure DeclareFuncType(ft: tai_functype);
|
procedure DeclareFuncType(ft: tai_functype);
|
||||||
procedure DeclareExportName(en: tai_export_name);
|
procedure DeclareExportName(en: tai_export_name);
|
||||||
@ -327,6 +329,7 @@ implementation
|
|||||||
ImportIndex:=-1;
|
ImportIndex:=-1;
|
||||||
FuncIndex:=-1;
|
FuncIndex:=-1;
|
||||||
SymbolIndex:=-1;
|
SymbolIndex:=-1;
|
||||||
|
GlobalIndex:=-1;
|
||||||
AliasOf:='';
|
AliasOf:='';
|
||||||
ExtraData:=nil;
|
ExtraData:=nil;
|
||||||
end;
|
end;
|
||||||
@ -614,6 +617,18 @@ implementation
|
|||||||
CurrObjSec.ObjRelocations.Add(objreloc);
|
CurrObjSec.ObjRelocations.Add(objreloc);
|
||||||
WriteUleb5(CurrObjSec,Data);
|
WriteUleb5(CurrObjSec,Data);
|
||||||
end;
|
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
|
else
|
||||||
internalerror(2021092501);
|
internalerror(2021092501);
|
||||||
end;
|
end;
|
||||||
@ -639,6 +654,19 @@ implementation
|
|||||||
FFuncTypes[result]:=TWasmFuncType.Create(wft);
|
FFuncTypes[result]:=TWasmFuncType.Create(wft);
|
||||||
end;
|
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);
|
procedure TWasmObjData.DeclareGlobalType(gt: tai_globaltype);
|
||||||
var
|
var
|
||||||
ObjSymExtraData: TWasmObjSymbolExtraData;
|
ObjSymExtraData: TWasmObjSymbolExtraData;
|
||||||
@ -998,6 +1026,13 @@ implementation
|
|||||||
end;
|
end;
|
||||||
RELOC_TYPE_INDEX_LEB:
|
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
|
else
|
||||||
internalerror(2021092510);
|
internalerror(2021092510);
|
||||||
end;
|
end;
|
||||||
@ -1097,6 +1132,15 @@ implementation
|
|||||||
WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
|
WriteUleb(relout,objrel.DataOffset+objsec.FileSectionOfs);
|
||||||
WriteUleb(relout,objrel.TypeIndex);
|
WriteUleb(relout,objrel.TypeIndex);
|
||||||
end;
|
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
|
else
|
||||||
internalerror(2021092507);
|
internalerror(2021092507);
|
||||||
end;
|
end;
|
||||||
@ -1112,7 +1156,10 @@ implementation
|
|||||||
cur_seg_ofs: qword = 0;
|
cur_seg_ofs: qword = 0;
|
||||||
types_count,
|
types_count,
|
||||||
imports_count, NextImportFunctionIndex, NextFunctionIndex,
|
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;
|
import_functions_count: Integer = 0;
|
||||||
export_functions_count: Integer = 0;
|
export_functions_count: Integer = 0;
|
||||||
functions_count: Integer = 0;
|
functions_count: Integer = 0;
|
||||||
@ -1130,6 +1177,11 @@ implementation
|
|||||||
for i:=0 to Data.ObjSymbolList.Count-1 do
|
for i:=0 to Data.ObjSymbolList.Count-1 do
|
||||||
begin
|
begin
|
||||||
objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
|
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
|
if IsExternalFunction(objsym) then
|
||||||
Inc(import_functions_count);
|
Inc(import_functions_count);
|
||||||
if (objsym.typ=AT_FUNCTION) and not objsym.IsAlias then
|
if (objsym.typ=AT_FUNCTION) and not objsym.IsAlias then
|
||||||
@ -1192,21 +1244,35 @@ implementation
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
imports_count:=3+import_functions_count;
|
imports_count:=2+import_globals_count+import_functions_count;
|
||||||
WriteUleb(FWasmSections[wsiImport],imports_count);
|
WriteUleb(FWasmSections[wsiImport],imports_count);
|
||||||
{ import[0] }
|
{ import memories }
|
||||||
WriteName(FWasmSections[wsiImport],'env');
|
WriteName(FWasmSections[wsiImport],'env');
|
||||||
WriteName(FWasmSections[wsiImport],'__linear_memory');
|
WriteName(FWasmSections[wsiImport],'__linear_memory');
|
||||||
WriteByte(FWasmSections[wsiImport],$02); { mem }
|
WriteByte(FWasmSections[wsiImport],$02); { mem }
|
||||||
WriteByte(FWasmSections[wsiImport],$00); { min }
|
WriteByte(FWasmSections[wsiImport],$00); { min }
|
||||||
WriteUleb(FWasmSections[wsiImport],1); { 1 page }
|
WriteUleb(FWasmSections[wsiImport],1); { 1 page }
|
||||||
{ import[1] }
|
{ import globals }
|
||||||
WriteName(FWasmSections[wsiImport],'env');
|
NextGlobalIndex:=0;
|
||||||
WriteName(FWasmSections[wsiImport],'__stack_pointer');
|
for i:=0 to Data.ObjSymbolList.Count-1 do
|
||||||
WriteByte(FWasmSections[wsiImport],$03); { global }
|
begin
|
||||||
WriteByte(FWasmSections[wsiImport],$7F); { i32 }
|
objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
|
||||||
WriteByte(FWasmSections[wsiImport],$01); { var }
|
if (objsym.bind=AB_EXTERNAL) and (objsym.typ=AT_WASM_GLOBAL) then
|
||||||
{ import[2]..import[imports_count-2] }
|
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;
|
NextImportFunctionIndex:=0;
|
||||||
for i:=0 to Data.ObjSymbolList.Count-1 do
|
for i:=0 to Data.ObjSymbolList.Count-1 do
|
||||||
begin
|
begin
|
||||||
@ -1225,7 +1291,7 @@ implementation
|
|||||||
WriteUleb(FWasmSections[wsiImport],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).TypeIdx);
|
WriteUleb(FWasmSections[wsiImport],TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name)).TypeIdx);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
{ import[imports_count-1] }
|
{ import tables }
|
||||||
WriteName(FWasmSections[wsiImport],'env');
|
WriteName(FWasmSections[wsiImport],'env');
|
||||||
WriteName(FWasmSections[wsiImport],'__indirect_function_table');
|
WriteName(FWasmSections[wsiImport],'__indirect_function_table');
|
||||||
WriteByte(FWasmSections[wsiImport],$01); { table }
|
WriteByte(FWasmSections[wsiImport],$01); { table }
|
||||||
@ -1246,6 +1312,60 @@ implementation
|
|||||||
end;
|
end;
|
||||||
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
|
if export_functions_count>0 then
|
||||||
begin
|
begin
|
||||||
WriteUleb(FWasmSections[wsiExport],export_functions_count);
|
WriteUleb(FWasmSections[wsiExport],export_functions_count);
|
||||||
@ -1264,7 +1384,21 @@ implementation
|
|||||||
for i:=0 to Data.ObjSymbolList.Count-1 do
|
for i:=0 to Data.ObjSymbolList.Count-1 do
|
||||||
begin
|
begin
|
||||||
objsym:=TWasmObjSymbol(Data.ObjSymbolList[i]);
|
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
|
begin
|
||||||
objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
|
objsym.SymbolIndex:=FWasmSymbolTableEntriesCount;
|
||||||
Inc(FWasmSymbolTableEntriesCount);
|
Inc(FWasmSymbolTableEntriesCount);
|
||||||
@ -1355,6 +1489,11 @@ implementation
|
|||||||
Inc(section_nr);
|
Inc(section_nr);
|
||||||
WriteWasmSection(wsiFunction);
|
WriteWasmSection(wsiFunction);
|
||||||
Inc(section_nr);
|
Inc(section_nr);
|
||||||
|
if globals_count>0 then
|
||||||
|
begin
|
||||||
|
WriteWasmSection(wsiGlobal);
|
||||||
|
Inc(section_nr);
|
||||||
|
end;
|
||||||
if export_functions_count>0 then
|
if export_functions_count>0 then
|
||||||
begin
|
begin
|
||||||
WriteWasmSection(wsiExport);
|
WriteWasmSection(wsiExport);
|
||||||
|
@ -625,9 +625,7 @@ uses
|
|||||||
internalerror(2021092012);
|
internalerror(2021092012);
|
||||||
if (ref^.base<>NR_NO) or (ref^.index<>NR_NO) or (ref^.offset<>0) then
|
if (ref^.base<>NR_NO) or (ref^.index<>NR_NO) or (ref^.offset<>0) then
|
||||||
internalerror(2021092013);
|
internalerror(2021092013);
|
||||||
if ref^.symbol.Name<>'__stack_pointer' then
|
result:=6;
|
||||||
internalerror(2021092014);
|
|
||||||
result:=1+UlebSize(0);
|
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
internalerror(2021092011);
|
internalerror(2021092011);
|
||||||
@ -1246,9 +1244,7 @@ uses
|
|||||||
internalerror(2021092012);
|
internalerror(2021092012);
|
||||||
if (ref^.base<>NR_NO) or (ref^.index<>NR_NO) or (ref^.offset<>0) then
|
if (ref^.base<>NR_NO) or (ref^.index<>NR_NO) or (ref^.offset<>0) then
|
||||||
internalerror(2021092013);
|
internalerror(2021092013);
|
||||||
if ref^.symbol.Name<>'__stack_pointer' then
|
objdata.writeReloc(0,5,TWasmObjData(ObjData).globalref(ref^.symbol),RELOC_GLOBAL_INDEX_LEB);
|
||||||
internalerror(2021092014);
|
|
||||||
WriteUleb(0);
|
|
||||||
end;
|
end;
|
||||||
else
|
else
|
||||||
internalerror(2021092011);
|
internalerror(2021092011);
|
||||||
|
Loading…
Reference in New Issue
Block a user