mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-06-01 18:02:34 +02:00
+ implemented WebAssembly code generator support for funcref and externref data
types, using new register types R_FUNCREFREGISTER and R_EXTERNREFREGISTER
This commit is contained in:
parent
e555eddeda
commit
11712658b0
@ -241,7 +241,11 @@ interface
|
||||
{ used on llvm for tracking metadata (every unique metadata has its own base register) }
|
||||
R_METADATAREGISTER,{ = 8 }
|
||||
{ optional MAC16 (16 bit multiply-accumulate) registers on Xtensa }
|
||||
R_MAC16REGISTER { = 9 }
|
||||
R_MAC16REGISTER, { = 9 }
|
||||
{ WebAssembly externref }
|
||||
R_EXTERNREFREGISTER, { = 10 }
|
||||
{ WebAssembly funcref }
|
||||
R_FUNCREFREGISTER { = 11 }
|
||||
|
||||
{ do not add more than 16 elements (ifdef by cpu type if needed)
|
||||
so we can store this in one nibble and pack TRegister
|
||||
|
@ -41,6 +41,8 @@ interface
|
||||
function getintregister(list:TAsmList;size:Tcgsize):Tregister;override;
|
||||
function getfpuregister(list:TAsmList;size:Tcgsize):Tregister;override;
|
||||
function getaddressregister(list:TAsmList):Tregister;override;
|
||||
function getfuncrefregister(list:TAsmList):Tregister;
|
||||
function getexternrefregister(list:TAsmList):Tregister;
|
||||
procedure do_register_allocation(list:TAsmList;headertai:tai);override;
|
||||
end;
|
||||
|
||||
@ -73,6 +75,10 @@ implementation
|
||||
[RS_R0],first_fpu_imreg,[]);
|
||||
rg[R_MMREGISTER]:=trgcpu.create(R_MMREGISTER,R_SUBNONE,
|
||||
[RS_R0],first_mm_imreg,[]);
|
||||
rg[R_FUNCREFREGISTER]:=Trgcpu.create(R_FUNCREFREGISTER,R_SUBNONE,
|
||||
[RS_R0],first_funcref_imreg,[]);
|
||||
rg[R_EXTERNREFREGISTER]:=Trgcpu.create(R_EXTERNREFREGISTER,R_SUBNONE,
|
||||
[RS_R0],first_externref_imreg,[]);
|
||||
end;
|
||||
|
||||
|
||||
@ -81,6 +87,8 @@ implementation
|
||||
rg[R_INTREGISTER].free;
|
||||
rg[R_FPUREGISTER].free;
|
||||
rg[R_MMREGISTER].free;
|
||||
rg[R_FUNCREFREGISTER].free;
|
||||
rg[R_EXTERNREFREGISTER].free;
|
||||
inherited done_register_allocators;
|
||||
end;
|
||||
|
||||
@ -112,6 +120,18 @@ implementation
|
||||
end;
|
||||
|
||||
|
||||
function tcgwasm.getfuncrefregister(list:TAsmList):Tregister;
|
||||
begin
|
||||
result:=rg[R_FUNCREFREGISTER].getregister(list,R_SUBNONE);
|
||||
end;
|
||||
|
||||
|
||||
function tcgwasm.getexternrefregister(list:TAsmList):Tregister;
|
||||
begin
|
||||
result:=rg[R_EXTERNREFREGISTER].getregister(list,R_SUBNONE);
|
||||
end;
|
||||
|
||||
|
||||
procedure tcgwasm.do_register_allocation(list:TAsmList;headertai:tai);
|
||||
begin
|
||||
{ We only run the "register allocation" once for an arbitrary allocator,
|
||||
|
@ -230,6 +230,12 @@ uses
|
||||
{ MM Super register first and last }
|
||||
first_mm_imreg = 4;
|
||||
|
||||
{ funcref Super register first and last }
|
||||
first_funcref_imreg = 4;
|
||||
|
||||
{ externref Super register first and last }
|
||||
first_externref_imreg = 4;
|
||||
|
||||
regnumber_table : array[tregisterindex] of tregister = (
|
||||
{$i rwasmnum.inc}
|
||||
);
|
||||
|
@ -65,6 +65,8 @@ uses
|
||||
procedure decstack(list : TAsmList;slots: longint);
|
||||
|
||||
class function def2regtyp(def: tdef): tregistertype; override;
|
||||
function getintregister(list:TAsmList;size:tdef):Tregister;override;
|
||||
function getregisterfordef(list: TAsmList;size:tdef):Tregister;override;
|
||||
|
||||
procedure a_load_const_cgpara(list : TAsmList;tosize : tdef;a : tcgint;const cgpara : TCGPara);override;
|
||||
|
||||
@ -256,7 +258,7 @@ implementation
|
||||
defutil,cpupi,
|
||||
aasmtai,aasmcpu,
|
||||
symtable,symcpu,
|
||||
procinfo,cpuinfo,cgcpu,tgobj,tgcpu,paramgr;
|
||||
procinfo,cpuinfo,cgobj,cgcpu,tgobj,tgcpu,paramgr;
|
||||
|
||||
const
|
||||
TOpCG2IAsmOp : array[topcg] of TAsmOp=(
|
||||
@ -364,13 +366,39 @@ implementation
|
||||
|
||||
class function thlcgwasm.def2regtyp(def: tdef): tregistertype;
|
||||
begin
|
||||
if (def.typ=recorddef) and (def.size in [4,8]) and (trecorddef(def).contains_float_field) then
|
||||
if is_wasm_externref(def) then
|
||||
result:=R_EXTERNREFREGISTER
|
||||
else if is_wasm_funcref(def) then
|
||||
result:=R_FUNCREFREGISTER
|
||||
else if (def.typ=recorddef) and (def.size in [4,8]) and (trecorddef(def).contains_float_field) then
|
||||
result:=R_FPUREGISTER
|
||||
else
|
||||
result:=inherited;
|
||||
end;
|
||||
|
||||
|
||||
function thlcgwasm.getintregister(list:TAsmList;size:tdef):Tregister;
|
||||
begin
|
||||
if is_wasm_reference_type(size) then
|
||||
internalerror(2023060702)
|
||||
else
|
||||
result:=inherited;
|
||||
end;
|
||||
|
||||
|
||||
function thlcgwasm.getregisterfordef(list: TAsmList;size:tdef):Tregister;
|
||||
begin
|
||||
case def2regtyp(size) of
|
||||
R_EXTERNREFREGISTER:
|
||||
result:=TCgWasm(cg).getexternrefregister(list);
|
||||
R_FUNCREFREGISTER:
|
||||
result:=TCgWasm(cg).getfuncrefregister(list);
|
||||
else
|
||||
result:=inherited;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure thlcgwasm.a_load_const_cgpara(list: TAsmList; tosize: tdef; a: tcgint; const cgpara: TCGPara);
|
||||
begin
|
||||
tosize:=get_para_push_size(tosize);
|
||||
@ -1024,7 +1052,17 @@ implementation
|
||||
end;
|
||||
else
|
||||
internalerror(2011010302);
|
||||
end
|
||||
end;
|
||||
R_FUNCREFREGISTER:
|
||||
begin
|
||||
list.concat(taicpu.op_none(a_ref_null_funcref));
|
||||
incstack(list,1);
|
||||
end;
|
||||
R_EXTERNREFREGISTER:
|
||||
begin
|
||||
list.concat(taicpu.op_none(a_ref_null_externref));
|
||||
incstack(list,1);
|
||||
end;
|
||||
else
|
||||
internalerror(2011010301);
|
||||
end;
|
||||
|
@ -54,7 +54,7 @@ implementation
|
||||
globtype,globals,
|
||||
cgobj,
|
||||
tgobj,
|
||||
symtype,symdef,symcpu;
|
||||
symtype,symdef,symconst,symcpu;
|
||||
|
||||
{ trgcpu }
|
||||
|
||||
@ -326,7 +326,9 @@ implementation
|
||||
spill_temps : tspilltemps;
|
||||
templist : TAsmList;
|
||||
intrg,
|
||||
fprg : trgcpu;
|
||||
fprg,
|
||||
frrg,
|
||||
errg : trgcpu;
|
||||
p,q : tai;
|
||||
size : longint;
|
||||
|
||||
@ -340,6 +342,7 @@ implementation
|
||||
pidx : integer;
|
||||
t: treftemppos;
|
||||
def: tdef;
|
||||
wasmfuncreftype: tprocvardef;
|
||||
|
||||
begin
|
||||
{ Since there are no actual registers, we simply spill everything. We
|
||||
@ -350,9 +353,13 @@ implementation
|
||||
{ get references to all register allocators }
|
||||
intrg:=trgcpu(cg.rg[R_INTREGISTER]);
|
||||
fprg:=trgcpu(cg.rg[R_FPUREGISTER]);
|
||||
frrg:=trgcpu(cg.rg[R_FUNCREFREGISTER]);
|
||||
errg:=trgcpu(cg.rg[R_EXTERNREFREGISTER]);
|
||||
{ determine the live ranges of all registers }
|
||||
intrg.insert_regalloc_info_all(list);
|
||||
fprg.insert_regalloc_info_all(list);
|
||||
frrg.insert_regalloc_info_all(list);
|
||||
errg.insert_regalloc_info_all(list);
|
||||
{ Don't do the actual allocation when -sr is passed }
|
||||
if (cs_no_regalloc in current_settings.globalswitches) then
|
||||
exit;
|
||||
@ -361,8 +368,13 @@ implementation
|
||||
{ allocate room to store the virtual register -> temp mapping }
|
||||
spill_temps[R_INTREGISTER]:=allocmem(sizeof(treference)*intrg.maxreg);
|
||||
spill_temps[R_FPUREGISTER]:=allocmem(sizeof(treference)*fprg.maxreg);
|
||||
spill_temps[R_FUNCREFREGISTER]:=allocmem(sizeof(treference)*frrg.maxreg);
|
||||
spill_temps[R_EXTERNREFREGISTER]:=allocmem(sizeof(treference)*errg.maxreg);
|
||||
{ List to insert temp allocations into }
|
||||
templist:=TAsmList.create;
|
||||
{ }
|
||||
wasmfuncreftype:=cprocvardef.create(normal_function_level,true);
|
||||
include(wasmfuncreftype.procoptions,po_wasm_funcref);
|
||||
{ allocate/replace all registers }
|
||||
p:=headertai;
|
||||
insbefore := nil;
|
||||
@ -408,6 +420,16 @@ implementation
|
||||
else
|
||||
internalerror(2020120804);
|
||||
end;
|
||||
R_FUNCREFREGISTER:
|
||||
begin
|
||||
size:=0;
|
||||
def:=wasmfuncreftype;
|
||||
end;
|
||||
R_EXTERNREFREGISTER:
|
||||
begin
|
||||
size:=0;
|
||||
def:=wasmvoidexternreftype;
|
||||
end;
|
||||
else
|
||||
internalerror(2010122912);
|
||||
end;
|
||||
@ -445,7 +467,11 @@ implementation
|
||||
list.insertListBefore(nil, templist);
|
||||
freemem(spill_temps[R_INTREGISTER]);
|
||||
freemem(spill_temps[R_FPUREGISTER]);
|
||||
freemem(spill_temps[R_FUNCREFREGISTER]);
|
||||
freemem(spill_temps[R_EXTERNREFREGISTER]);
|
||||
templist.free;
|
||||
{ Not needed anymore }
|
||||
wasmfuncreftype.owner.deletedef(wasmfuncreftype);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
@ -83,6 +83,7 @@ unit tgcpu;
|
||||
procedure ungettemp(list: TAsmList; const ref : treference); override;
|
||||
procedure allocframepointer(list: TAsmList; out ref: treference);
|
||||
procedure allocbasepointer(list: TAsmList; out ref: treference);
|
||||
procedure getlocal(list: TAsmList; size: asizeint; alignment: shortint; def: tdef; var ref : treference); override;
|
||||
end;
|
||||
|
||||
function defToWasmBasic(def: tdef; var wbt: TWasmBasicType): Boolean;
|
||||
@ -239,6 +240,13 @@ unit tgcpu;
|
||||
else
|
||||
internalerror(2020121801);
|
||||
end
|
||||
else if Assigned(def) and is_wasm_reference_type(def) then
|
||||
begin
|
||||
if defToWasmBasic(def, wbt) then
|
||||
allocLocalVarToRef(wbt, ref)
|
||||
else
|
||||
internalerror(2023060701);
|
||||
end
|
||||
else
|
||||
inherited;
|
||||
end;
|
||||
@ -288,6 +296,21 @@ unit tgcpu;
|
||||
updateFirstTemp;
|
||||
end;
|
||||
|
||||
procedure ttgwasm.getlocal(list: TAsmList; size: asizeint; alignment: shortint; def: tdef; var ref : treference);
|
||||
var
|
||||
wbt: TWasmBasicType;
|
||||
begin
|
||||
if is_wasm_reference_type(def) then
|
||||
begin
|
||||
if defToWasmBasic(def, wbt) then
|
||||
allocLocalVarToRef(wbt, ref)
|
||||
else
|
||||
internalerror(2023060703);
|
||||
end
|
||||
else
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TWasmLocalVars.alloc(bt: TWasmBasicType): integer;
|
||||
var
|
||||
i : integer;
|
||||
|
@ -2490,9 +2490,9 @@ implementation
|
||||
(0, 1, 2, 3, 6, 7, 5, 4);
|
||||
maxsupreg: array[tregistertype] of tsuperregister=
|
||||
{$ifdef x86_64}
|
||||
(0, 16, 9, 8, 32, 32, 8, 0, 0, 0);
|
||||
(0, 16, 9, 8, 32, 32, 8, 0, 0, 0, 0, 0);
|
||||
{$else x86_64}
|
||||
(0, 8, 9, 8, 8, 32, 8, 0, 0, 0);
|
||||
(0, 8, 9, 8, 8, 32, 8, 0, 0, 0, 0, 0);
|
||||
{$endif x86_64}
|
||||
var
|
||||
rs: tsuperregister;
|
||||
|
Loading…
Reference in New Issue
Block a user