mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-12-09 10:47:16 +01:00
+ generate the global section in the wasm internal linker exe writer
This commit is contained in:
parent
0d5f7fa66b
commit
d03963afe9
@ -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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user