{ Copyright (c) 2019 by Dmitry Boyarintsev This unit implements the code generator for the WebAssembly This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. **************************************************************************** } unit cgcpu; {$i fpcdefs.inc} interface uses globtype,parabase, cgbase,cgutils,cgobj,cghlcpu, aasmbase,aasmtai,aasmdata,aasmcpu, cpubase,cpuinfo, node,symconst,SymType,symdef, rgcpu; type TCgWasm=class(thlbasecgcpu) public procedure init_register_allocators;override; procedure done_register_allocators;override; 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; procedure a_label_pascal_goto_target(list : TAsmList;l : tasmlabel);override; end; procedure create_codegen; implementation uses globals,verbose,systems,cutils, paramgr,fmodule, tgobj, procinfo,cpupi; {**************************************************************************** Assembler code ****************************************************************************} procedure TCgWasm.init_register_allocators; begin inherited init_register_allocators; {$ifndef cpu64bitaddr} rg[R_INTREGISTER]:=Trgcpu.create(R_INTREGISTER,R_SUBD, [RS_R0],first_int_imreg,[]); {$else not cpu64bitaddr} rg[R_INTREGISTER]:=Trgcpu.create(R_INTREGISTER,R_SUBQ, [RS_R0],first_int_imreg,[]); {$endif not cpu64bitaddr} rg[R_FPUREGISTER]:=trgcpu.create(R_FPUREGISTER,R_SUBFS, [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; procedure TCgWasm.done_register_allocators; begin 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; function TCgWasm.getintregister(list:TAsmList;size:Tcgsize):Tregister; begin if not(size in [OS_64,OS_S64]) then result:=rg[R_INTREGISTER].getregister(list,R_SUBD) else result:=rg[R_INTREGISTER].getregister(list,R_SUBQ); end; function TCgWasm.getfpuregister(list:TAsmList;size:Tcgsize):Tregister; begin if size=OS_F64 then result:=rg[R_FPUREGISTER].getregister(list,R_SUBFD) else result:=rg[R_FPUREGISTER].getregister(list,R_SUBFS); end; function tcgwasm.getaddressregister(list:TAsmList):Tregister; begin { avoid problems in the compiler where int and addr registers are mixed for now; we currently don't have to differentiate between the two as far as the jvm backend is concerned } result:=rg[R_INTREGISTER].getregister(list,R_SUBD) 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, which will perform the register->temp mapping for all register types. This allows us to easily reuse temps. } trgcpu(rg[R_INTREGISTER]).do_all_register_allocation(list,headertai); end; procedure tcgwasm.a_label_pascal_goto_target(list : TAsmList;l : tasmlabel); begin tcpuprocinfo(current_procinfo).add_goto_target(l); inherited; end; procedure create_codegen; begin cg:=tcgwasm.Create; end; end.