+ generate the global section in the wasm internal linker exe writer

This commit is contained in:
Nikolay Nikolov 2024-01-01 21:11:28 +02:00
parent 0d5f7fa66b
commit d03963afe9

View File

@ -41,17 +41,30 @@ interface
type
TWasmObjSymbolExtraData = class;
TGlobalInitializer = record
case typ:TWasmBasicType of
wbt_i32: (init_i32: Int32);
wbt_i64: (init_i64: Int64);
wbt_f32: (init_f32: Single);
wbt_f64: (init_f64: Double);
end;
{ TWasmObjSymbolLinkingData }
TWasmObjSymbolLinkingData = class
public
ImportModule: string;
ImportName: string;
FuncType: TWasmFuncType;
ExeFunctionIndex: Integer;
ExeIndirectFunctionTableIndex: Integer;
ExeTypeIndex: Integer;
GlobalType: TWasmBasicType;
GlobalIsMutable: Boolean;
GlobalInitializer: TGlobalInitializer;
constructor Create;
destructor Destroy;override;
end;
@ -369,6 +382,36 @@ implementation
until Done;
end;
{$ifdef FPC_LITTLE_ENDIAN}
procedure WriteF32LE(d: tdynamicarray; v: Single);
begin
d.write(v,4);
end;
procedure WriteF64LE(d: tdynamicarray; v: Double);
begin
d.write(v,8);
end;
{$else FPC_LITTLE_ENDIAN}
procedure WriteF32LE(d: tdynamicarray; v: Single);
var
tmpI: UInt32;
begin
Move(v,tmpI,4);
tmpI:=SwapEndian(tmpI);
d.write(tmpI,4);
end;
procedure WriteF64LE(d: tdynamicarray; v: Double);
var
tmpI: UInt64;
begin
Move(v,tmpI,8);
tmpI:=SwapEndian(tmpI);
d.write(tmpI,8);
end;
{$endif FPC_LITTLE_ENDIAN}
procedure WriteByte(d: tdynamicarray; b: byte);
begin
d.write(b,1);
@ -2345,6 +2388,7 @@ implementation
IsMutable: Boolean;
IsExported: Boolean;
ExportName: ansistring;
GlobalInit: TGlobalInitializer;
end;
GlobalTypeImportsCount: uint32;
@ -3205,12 +3249,11 @@ implementation
function ReadGlobalSection: Boolean;
function ParseExpr: Boolean;
function ParseExpr(out Init: TGlobalInitializer): Boolean;
var
B: Byte;
tmpbuf: array [1..8] of Byte;
tmpInt32: int32;
tmpInt64: int64;
B, B2: Byte;
tmpU32: UInt32;
tmpU64: UInt64;
begin
Result:=False;
repeat
@ -3220,20 +3263,46 @@ implementation
$0B: { end }
;
$41: { i32.const }
if not ReadSleb32(tmpInt32) then
exit;
begin
Init.typ:=wbt_i32;
if not ReadSleb32(Init.init_i32) then
exit;
end;
$42: { i64.const }
if not ReadSleb(tmpInt64) then
exit;
begin
Init.typ:=wbt_i64;
if not ReadSleb(Init.init_i64) then
exit;
end;
$43: { f32.const }
if not Read(tmpbuf, 4) then
exit;
begin
Init.typ:=wbt_f32;
if not Read(tmpU32, 4) then
exit;
{$ifdef FPC_BIG_ENDIAN}
tmpU32:=SwapEndian(tmpU32);
{$endif FPC_BIG_ENDIAN}
Move(tmpU32,Init.init_f32,4);
end;
$44: { f64.const }
if not Read(tmpbuf, 8) then
exit;
begin
Init.typ:=wbt_f64;
if not Read(tmpU64, 8) then
exit;
{$ifdef FPC_BIG_ENDIAN}
tmpU64:=SwapEndian(tmpU64);
{$endif FPC_BIG_ENDIAN}
Move(tmpU64,Init.init_f64,8);
end;
$D0: { ref.null }
if not Read(tmpbuf, 1) then
exit;
begin
if not Read(B2, 1) then
exit;
if not decode_wasm_basic_type(B2, Init.typ) then
exit;
if not (Init.typ in WasmReferenceTypes) then
exit;
end;
else
begin
InputError('Unsupported opcode in global initializer');
@ -3292,11 +3361,16 @@ implementation
exit;
end;
end;
if not ParseExpr then
if not ParseExpr(GlobalInit) then
begin
InputError('Error parsing the global initializer expression in the global section');
exit;
end;
if GlobalInit.typ<>valtype then
begin
InputError('Initializer expression for global produces a type, which does not match the type of the global');
exit;
end;
end;
if AReader.Pos<>(SectionStart+SectionSize) then
begin
@ -3969,9 +4043,14 @@ implementation
objsym.objsection:=ObjData.createsection('.wasm_globals.n_'+SymName,1,[oso_Data,oso_load],true);
if objsym.objsection.Size=0 then
objsym.objsection.WriteZeros(1);
if (SymFlags and WASM_SYM_EXPLICIT_NAME)=0 then
TWasmObjSection(objsym.objsection).MainFuncSymbol:=objsym;
objsym.offset:=0;
objsym.size:=1;
objsym.LinkingData.GlobalInitializer:=GlobalTypes[SymIndex].GlobalInit;
end;
objsym.LinkingData.GlobalType:=GlobalTypes[SymIndex].valtype;
objsym.LinkingData.GlobalIsMutable:=GlobalTypes[SymIndex].IsMutable;
end;
byte(SYMTAB_SECTION),
byte(SYMTAB_EVENT),
@ -4295,6 +4374,63 @@ implementation
WriteUleb(FWasmSections[wsiElement],FIndirectFunctionTable[i].FuncIdx);
end;
procedure WriteGlobalSection;
var
exesec: TExeSection;
globals_count, i: Integer;
objsec: TWasmObjSection;
begin
exesec:=FindExeSection('.wasm_globals');
if not assigned(exesec) then
internalerror(2024010112);
globals_count:=exesec.ObjSectionList.Count;
if globals_count<>exesec.Size then
internalerror(2024010113);
WriteUleb(FWasmSections[wsiGlobal],globals_count);
for i:=0 to exesec.ObjSectionList.Count-1 do
begin
objsec:=TWasmObjSection(exesec.ObjSectionList[i]);
WriteByte(FWasmSections[wsiGlobal],encode_wasm_basic_type(objsec.MainFuncSymbol.LinkingData.GlobalType));
if objsec.MainFuncSymbol.LinkingData.GlobalIsMutable then
WriteByte(FWasmSections[wsiGlobal],1)
else
WriteByte(FWasmSections[wsiGlobal],0);
{ initializer expr }
with objsec.MainFuncSymbol.LinkingData.GlobalInitializer do
case typ of
wbt_i32:
begin
WriteByte(FWasmSections[wsiGlobal],$41); { i32.const }
WriteSleb(FWasmSections[wsiGlobal],init_i32);
end;
wbt_i64:
begin
WriteByte(FWasmSections[wsiGlobal],$42); { i64.const }
WriteSleb(FWasmSections[wsiGlobal],init_i64);
end;
wbt_f32:
begin
WriteByte(FWasmSections[wsiGlobal],$43); { f32.const }
WriteF32LE(FWasmSections[wsiGlobal],init_f32);
end;
wbt_f64:
begin
WriteByte(FWasmSections[wsiGlobal],$44); { f64.const }
WriteF64LE(FWasmSections[wsiGlobal],init_f64);
end;
wbt_funcref,
wbt_externref:
begin
WriteByte(FWasmSections[wsiGlobal],$D0); { ref.null }
WriteByte(FWasmSections[wsiGlobal],encode_wasm_basic_type(typ));
end;
else
internalerror(2024010114);
end;
WriteByte(FWasmSections[wsiGlobal],$0B); { end }
end;
end;
begin
result:=false;
@ -4303,6 +4439,7 @@ implementation
WriteCodeSegments;
WriteDataSegments;
WriteTableAndElemSections;
WriteGlobalSection;
WriteUleb(FWasmSections[wsiMemory],1);
WriteByte(FWasmSections[wsiMemory],0);
@ -4317,6 +4454,7 @@ implementation
WriteWasmSection(wsiFunction);
WriteWasmSection(wsiTable);
WriteWasmSection(wsiMemory);
WriteWasmSection(wsiGlobal);
WriteWasmSection(wsiElement);
WriteWasmSection(wsiDataCount);
WriteWasmSection(wsiCode);
@ -4496,14 +4634,19 @@ implementation
const
StackPointerSymStr='__stack_pointer';
var
objsym: TObjSymbol;
objsym: TWasmObjSymbol;
begin
if aname=StackPointerSymStr then
begin
internalObjData.createsection('*'+aname,1,[oso_Data,oso_load]);
objsym:=internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_WASM_GLOBAL);
objsym:=TWasmObjSymbol(internalObjData.SymbolDefine(aname,AB_GLOBAL,AT_WASM_GLOBAL));
objsym.size:=1;
objsym.ObjSection.WriteZeros(1);
TWasmObjSection(objsym.ObjSection).MainFuncSymbol:=objsym;
objsym.LinkingData.GlobalType:=wbt_i32;
objsym.LinkingData.GlobalIsMutable:=True;
objsym.LinkingData.GlobalInitializer.typ:=wbt_i32;
objsym.LinkingData.GlobalInitializer.init_i32:=0;
end
else
inherited;