mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-07 21:28:03 +02:00
* WebAssembly internal assembler writer: generate the function locals header
when assembling the tai_local directive, instead of injecting them manually in TWasmObjOutput.WriteFunctionCode. This makes function code offsets correct and avoids the need to manually adjust relocation fixups by adding the locals header size. It also fixes relative relocations, used in DWARF debug line info.
This commit is contained in:
parent
1a08d76ccb
commit
562ca0ad80
@ -1942,7 +1942,7 @@ Implementation
|
||||
ait_globaltype:
|
||||
TWasmObjData(ObjData).DeclareGlobalType(tai_globaltype(hp));
|
||||
ait_functype:
|
||||
TWasmObjData(ObjData).DeclareFuncType(tai_functype(hp));
|
||||
TWasmObjData(ObjData).DeclareFuncType_Pass0(tai_functype(hp));
|
||||
ait_tagtype:
|
||||
TWasmObjData(ObjData).DeclareTagType(tai_tagtype(hp));
|
||||
ait_export_name:
|
||||
@ -1952,7 +1952,7 @@ Implementation
|
||||
ait_import_name:
|
||||
TWasmObjData(ObjData).DeclareImportName(tai_import_name(hp));
|
||||
ait_local:
|
||||
TWasmObjData(ObjData).DeclareLocals(tai_local(hp));
|
||||
TWasmObjData(ObjData).DeclareLocals_Pass0(tai_local(hp));
|
||||
{$endif WASM}
|
||||
else
|
||||
;
|
||||
@ -2145,6 +2145,12 @@ Implementation
|
||||
Internalerror(2019100703);
|
||||
end;
|
||||
end;
|
||||
{$ifdef WASM}
|
||||
ait_functype:
|
||||
TWasmObjData(ObjData).DeclareFuncType_Pass1(tai_functype(hp));
|
||||
ait_local:
|
||||
TWasmObjData(ObjData).DeclareLocals_Pass1(tai_local(hp));
|
||||
{$endif WASM}
|
||||
else
|
||||
;
|
||||
end;
|
||||
@ -2602,6 +2608,12 @@ Implementation
|
||||
eabi_section.Data.write(ddword,4);
|
||||
eabi_section.Data.Seek(TmpDataPos);
|
||||
end;
|
||||
{$ifdef WASM}
|
||||
ait_functype:
|
||||
TWasmObjData(ObjData).DeclareFuncType_Pass2(tai_functype(hp));
|
||||
ait_local:
|
||||
TWasmObjData(ObjData).WriteLocals_Pass2(tai_local(hp));
|
||||
{$endif WASM}
|
||||
else
|
||||
;
|
||||
end;
|
||||
|
@ -119,8 +119,10 @@ interface
|
||||
GlobalType: TWasmBasicType;
|
||||
GlobalIsImmutable: Boolean;
|
||||
Locals: array of TWasmBasicType;
|
||||
EncodedLocals: tdynamicarray;
|
||||
constructor Create(HashObjectList: TFPHashObjectList; const s: TSymStr);
|
||||
procedure AddLocal(bastyp: TWasmBasicType);
|
||||
destructor Destroy; override;
|
||||
procedure AddLocals(alocals: TWasmLocalsDynArray);
|
||||
end;
|
||||
|
||||
{ TWasmObjSection }
|
||||
@ -131,7 +133,6 @@ interface
|
||||
SegSymIdx: Integer;
|
||||
SegOfs: qword;
|
||||
FileSectionOfs: qword;
|
||||
EncodedLocalsSize: qword;
|
||||
MainFuncSymbol: TWasmObjSymbol;
|
||||
CustomSectionIdx: Integer;
|
||||
constructor create(AList:TFPHashObjectList;const Aname:string;Aalign:longint;Aoptions:TObjSectionOptions);override;
|
||||
@ -175,12 +176,16 @@ interface
|
||||
function globalref(asmsym:TAsmSymbol):TObjSymbol;
|
||||
function ExceptionTagRef(asmsym:TAsmSymbol):TObjSymbol;
|
||||
procedure DeclareGlobalType(gt: tai_globaltype);
|
||||
procedure DeclareFuncType(ft: tai_functype);
|
||||
procedure DeclareFuncType_Pass0(ft: tai_functype);
|
||||
procedure DeclareFuncType_Pass1(ft: tai_functype);
|
||||
procedure DeclareFuncType_Pass2(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);
|
||||
procedure DeclareLocals(al: tai_local);
|
||||
procedure DeclareLocals_Pass0(al: tai_local);
|
||||
procedure DeclareLocals_Pass1(al: tai_local);
|
||||
procedure WriteLocals_Pass2(al: tai_local);
|
||||
procedure symbolpairdefine(akind: TSymbolPairKind;const asym, avalue: string);override;
|
||||
property FuncTypes: TWasmFuncTypeTable read FFuncTypes;
|
||||
end;
|
||||
@ -217,7 +222,6 @@ interface
|
||||
procedure WriteWasmCustomSection(wcst: TWasmCustomSectionType);
|
||||
function IsExternalFunction(sym: TObjSymbol): Boolean;
|
||||
function IsExportedFunction(sym: TWasmObjSymbol): Boolean;
|
||||
procedure WriteFunctionLocals(dest: tdynamicarray; ed: TWasmObjSymbolExtraData);
|
||||
procedure WriteFunctionCode(dest: tdynamicarray; objsym: TObjSymbol);
|
||||
procedure WriteSymbolTable;
|
||||
procedure WriteRelocationCodeTable(CodeSectionIndex: Integer);
|
||||
@ -735,15 +739,55 @@ implementation
|
||||
|
||||
constructor TWasmObjSymbolExtraData.Create(HashObjectList: TFPHashObjectList; const s: TSymStr);
|
||||
begin
|
||||
EncodedLocals:=nil;
|
||||
inherited Create(HashObjectList,s);
|
||||
TypeIdx:=-1;
|
||||
ExceptionTagTypeIdx:=-1;
|
||||
end;
|
||||
|
||||
procedure TWasmObjSymbolExtraData.AddLocal(bastyp: TWasmBasicType);
|
||||
destructor TWasmObjSymbolExtraData.Destroy;
|
||||
begin
|
||||
SetLength(Locals,Length(Locals)+1);
|
||||
Locals[High(Locals)]:=bastyp;
|
||||
EncodedLocals.Free;
|
||||
inherited Destroy;
|
||||
end;
|
||||
|
||||
procedure TWasmObjSymbolExtraData.AddLocals(alocals: TWasmLocalsDynArray);
|
||||
var
|
||||
i,
|
||||
rle_entries,
|
||||
cnt: Integer;
|
||||
lasttype: TWasmBasicType;
|
||||
begin
|
||||
Locals:=alocals;
|
||||
if Assigned(EncodedLocals) then
|
||||
internalerror(2024081502);
|
||||
EncodedLocals:=tdynamicarray.Create(64);
|
||||
if Length(Locals)=0 then
|
||||
begin
|
||||
WriteUleb(EncodedLocals,0);
|
||||
exit;
|
||||
end;
|
||||
|
||||
rle_entries:=1;
|
||||
for i:=low(Locals)+1 to high(Locals) do
|
||||
if Locals[i]<>Locals[i-1] then
|
||||
inc(rle_entries);
|
||||
|
||||
WriteUleb(EncodedLocals,rle_entries);
|
||||
lasttype:=Locals[Low(Locals)];
|
||||
cnt:=1;
|
||||
for i:=low(Locals)+1 to high(Locals) do
|
||||
if Locals[i]=Locals[i-1] then
|
||||
inc(cnt)
|
||||
else
|
||||
begin
|
||||
WriteUleb(EncodedLocals,cnt);
|
||||
WriteWasmBasicType(EncodedLocals,lasttype);
|
||||
lasttype:=Locals[i];
|
||||
cnt:=1;
|
||||
end;
|
||||
WriteUleb(EncodedLocals,cnt);
|
||||
WriteWasmBasicType(EncodedLocals,lasttype);
|
||||
end;
|
||||
|
||||
{****************************************************************************
|
||||
@ -1155,7 +1199,7 @@ implementation
|
||||
ObjSymExtraData.GlobalIsImmutable:=gt.immutable;
|
||||
end;
|
||||
|
||||
procedure TWasmObjData.DeclareFuncType(ft: tai_functype);
|
||||
procedure TWasmObjData.DeclareFuncType_Pass0(ft: tai_functype);
|
||||
var
|
||||
i: Integer;
|
||||
ObjSymExtraData: TWasmObjSymbolExtraData;
|
||||
@ -1166,6 +1210,16 @@ implementation
|
||||
ObjSymExtraData.TypeIdx:=i;
|
||||
end;
|
||||
|
||||
procedure TWasmObjData.DeclareFuncType_Pass1(ft: tai_functype);
|
||||
begin
|
||||
FLastFuncName:=ft.funcname;
|
||||
end;
|
||||
|
||||
procedure TWasmObjData.DeclareFuncType_Pass2(ft: tai_functype);
|
||||
begin
|
||||
FLastFuncName:=ft.funcname;
|
||||
end;
|
||||
|
||||
procedure TWasmObjData.DeclareTagType(tt: tai_tagtype);
|
||||
var
|
||||
ObjSymExtraData: TWasmObjSymbolExtraData;
|
||||
@ -1203,14 +1257,44 @@ implementation
|
||||
ObjSymExtraData.ImportName:=ain.importname;
|
||||
end;
|
||||
|
||||
procedure TWasmObjData.DeclareLocals(al: tai_local);
|
||||
procedure TWasmObjData.DeclareLocals_Pass0(al: tai_local);
|
||||
var
|
||||
ObjSymExtraData: TWasmObjSymbolExtraData;
|
||||
t: TWasmBasicType;
|
||||
begin
|
||||
ObjSymExtraData:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(FLastFuncName));
|
||||
for t in al.locals do
|
||||
ObjSymExtraData.AddLocal(t);
|
||||
ObjSymExtraData.AddLocals(al.locals);
|
||||
alloc(ObjSymExtraData.EncodedLocals.size);
|
||||
end;
|
||||
|
||||
procedure TWasmObjData.DeclareLocals_Pass1(al: tai_local);
|
||||
var
|
||||
ObjSymExtraData: TWasmObjSymbolExtraData;
|
||||
begin
|
||||
ObjSymExtraData:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(FLastFuncName));
|
||||
alloc(ObjSymExtraData.EncodedLocals.size);
|
||||
end;
|
||||
|
||||
procedure TWasmObjData.WriteLocals_Pass2(al: tai_local);
|
||||
var
|
||||
ObjSymExtraData: TWasmObjSymbolExtraData;
|
||||
d: tdynamicarray;
|
||||
buf: array [0..4095] of byte;
|
||||
bs,size: Integer;
|
||||
begin
|
||||
ObjSymExtraData:=TWasmObjSymbolExtraData(FObjSymbolsExtraDataList.Find(FLastFuncName));
|
||||
d:=ObjSymExtraData.EncodedLocals;
|
||||
d.seek(0);
|
||||
size:=d.size;
|
||||
while size>0 do
|
||||
begin
|
||||
if size<SizeOf(buf) then
|
||||
bs:=Integer(size)
|
||||
else
|
||||
bs:=SizeOf(buf);
|
||||
d.read(buf,bs);
|
||||
writebytes(buf,bs);
|
||||
dec(size,bs);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TWasmObjData.symbolpairdefine(akind: TSymbolPairKind; const asym, avalue: string);
|
||||
@ -1274,64 +1358,20 @@ implementation
|
||||
result:=false;
|
||||
end;
|
||||
|
||||
procedure TWasmObjOutput.WriteFunctionLocals(dest: tdynamicarray; ed: TWasmObjSymbolExtraData);
|
||||
var
|
||||
i,
|
||||
rle_entries,
|
||||
cnt: Integer;
|
||||
lasttype: TWasmBasicType;
|
||||
begin
|
||||
if Length(ed.Locals)=0 then
|
||||
begin
|
||||
WriteUleb(dest,0);
|
||||
exit;
|
||||
end;
|
||||
|
||||
rle_entries:=1;
|
||||
for i:=low(ed.Locals)+1 to high(ed.Locals) do
|
||||
if ed.Locals[i]<>ed.Locals[i-1] then
|
||||
inc(rle_entries);
|
||||
|
||||
WriteUleb(dest,rle_entries);
|
||||
lasttype:=ed.Locals[Low(ed.Locals)];
|
||||
cnt:=1;
|
||||
for i:=low(ed.Locals)+1 to high(ed.Locals) do
|
||||
if ed.Locals[i]=ed.Locals[i-1] then
|
||||
inc(cnt)
|
||||
else
|
||||
begin
|
||||
WriteUleb(dest,cnt);
|
||||
WriteWasmBasicType(dest,lasttype);
|
||||
lasttype:=ed.Locals[i];
|
||||
cnt:=1;
|
||||
end;
|
||||
WriteUleb(dest,cnt);
|
||||
WriteWasmBasicType(dest,lasttype);
|
||||
end;
|
||||
|
||||
procedure TWasmObjOutput.WriteFunctionCode(dest: tdynamicarray; objsym: TObjSymbol);
|
||||
var
|
||||
encoded_locals: tdynamicarray;
|
||||
ObjSymExtraData: TWasmObjSymbolExtraData;
|
||||
codelen: LongWord;
|
||||
ObjSection: TWasmObjSection;
|
||||
codeexprlen: QWord;
|
||||
codelen: QWord;
|
||||
begin
|
||||
ObjSymExtraData:=TWasmObjSymbolExtraData(FData.FObjSymbolsExtraDataList.Find(objsym.Name));
|
||||
ObjSection:=TWasmObjSection(objsym.objsection);
|
||||
ObjSection.Data.seek(objsym.address);
|
||||
codeexprlen:=objsym.size;
|
||||
codelen:=objsym.size;
|
||||
|
||||
encoded_locals:=tdynamicarray.Create(64);
|
||||
WriteFunctionLocals(encoded_locals,ObjSymExtraData);
|
||||
codelen:=encoded_locals.size+codeexprlen;
|
||||
WriteUleb(dest,codelen);
|
||||
encoded_locals.seek(0);
|
||||
CopyDynamicArray(encoded_locals,dest,encoded_locals.size);
|
||||
ObjSection.FileSectionOfs:=dest.size-objsym.offset;
|
||||
ObjSection.EncodedLocalsSize:=encoded_locals.size;
|
||||
CopyDynamicArray(ObjSection.Data,dest,codeexprlen);
|
||||
encoded_locals.Free;
|
||||
CopyDynamicArray(ObjSection.Data,dest,codelen);
|
||||
end;
|
||||
|
||||
procedure TWasmObjOutput.WriteSymbolTable;
|
||||
@ -1610,10 +1650,7 @@ implementation
|
||||
message1(asmw_e_illegal_unset_index,FuncSym.Name)
|
||||
else
|
||||
WriteUleb(relout,FuncSym.SymbolIndex);
|
||||
if (objrel.Addend+objrel.symbol.address)=0 then
|
||||
WriteSleb(relout,objrel.Addend+objrel.symbol.address) { addend to add to the address }
|
||||
else
|
||||
WriteSleb(relout,objrel.Addend+objrel.symbol.address+TWasmObjSection(objrel.symbol.objsection).EncodedLocalsSize); { addend to add to the address }
|
||||
WriteSleb(relout,objrel.Addend+objrel.symbol.address) { addend to add to the address }
|
||||
end
|
||||
else if assigned(objrel.symbol) and (objrel.symbol.typ=AT_WASM_GLOBAL) then
|
||||
begin
|
||||
|
Loading…
Reference in New Issue
Block a user