{ Copyright (C) 2019 Dmitry Boyarintsev This unit handles the temporary variables 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 tgcpu; {$i fpcdefs.inc} interface uses globtype, aasmdata, cgutils, symtype,tgobj; type { ttgwasm } ttgwasm = class(ttgobj) //protected // procedure getimplicitobjtemp(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference); // function getifspecialtemp(list: TAsmList; def: tdef; forcesize: asizeint; temptype: ttemptype; out ref: treference): boolean; procedure alloctemp(list: TAsmList; size: asizeint; alignment: shortint; temptype: ttemptype; def: tdef; fini: boolean; out ref: treference); override; public constructor create; override; procedure setfirsttemp(l : asizeint); override; //procedure getlocal(list: TAsmList; size: asizeint; alignment: shortint; def: tdef; var ref: treference); override; //procedure gethltemp(list: TAsmList; def: tdef; forcesize: asizeint; temptype: ttemptype; out ref: treference); override; //procedure gethltempmanaged(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference); override; end; implementation uses verbose, cgbase, symconst,symtable,symdef,symsym,symcpu,defutil, cpubase,aasmbase,aasmcpu, hlcgobj,hlcgcpu; { ttgwasm } //procedure ttgwasm.getimplicitobjtemp(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference); // var // sym: tsym; // pd: tprocdef; // begin // gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref); // list.concat(taicpu.op_sym(a_new,current_asmdata.RefAsmSymbol(tabstractrecorddef(def).jvm_full_typename(true),AT_METADATA))); // { the constructor doesn't return anything, so put a duplicate of the // self pointer on the evaluation stack for use as function result // after the constructor has run } // list.concat(taicpu.op_none(a_dup)); // thlcgjvm(hlcg).incstack(list,2); // { call the constructor } // sym:=tsym(tabstractrecorddef(def).symtable.find('CREATE')); // if assigned(sym) and // (sym.typ=procsym) then // begin // pd:=tprocsym(sym).find_bytype_parameterless(potype_constructor); // if not assigned(pd) then // internalerror(2011032701); // end // else // internalerror(2011060301); // hlcg.a_call_name(list,pd,pd.mangledname,[],nil,false); // thlcgjvm(hlcg).decstack(list,1); // { store reference to instance } // thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0); // end; //function ttgwasm.getifspecialtemp(list: TAsmList; def: tdef; forcesize: asizeint; temptype: ttemptype; out ref: treference): boolean; // var // eledef: tdef; // ndim: longint; // sym: tsym; // pd: tprocdef; // begin // result:=false; // case def.typ of // arraydef: // begin // if not is_dynamic_array(def) then // begin // { allocate an array of the right size } // gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref); // ndim:=0; // eledef:=def; // repeat // if forcesize<>-1 then // thlcgjvm(hlcg).a_load_const_stack(list,s32inttype,forcesize div tarraydef(eledef).elesize,R_INTREGISTER) // else // thlcgjvm(hlcg).a_load_const_stack(list,s32inttype,tarraydef(eledef).elecount,R_INTREGISTER); // eledef:=tarraydef(eledef).elementdef; // inc(ndim); // forcesize:=-1; // until (eledef.typ<>arraydef) or // is_dynamic_array(eledef); // eledef:=tarraydef(def).elementdef; // thlcgjvm(hlcg).g_newarray(list,def,ndim); // thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0); // result:=true; // end; // end; // recorddef: // begin // getimplicitobjtemp(list,def,temptype,ref); // result:=true; // end; // setdef: // begin // if tsetdef(def).elementdef.typ=enumdef then // begin // { load enum class type } // list.concat(taicpu.op_sym(a_ldc,current_asmdata.RefAsmSymbol(tcpuenumdef(tenumdef(tsetdef(def).elementdef).getbasedef).classdef.jvm_full_typename(true),AT_METADATA))); // thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1); // { call tenumset.noneOf() class method } // sym:=tsym(tobjectdef(java_juenumset).symtable.find('NONEOF')); // if assigned(sym) and // (sym.typ=procsym) then // begin // if tprocsym(sym).procdeflist.Count<>1 then // internalerror(2011062801); // pd:=tprocdef(tprocsym(sym).procdeflist[0]); // hlcg.a_call_name(list,pd,pd.mangledname,[],nil,false); // end; // { static calls method replaces parameter with set instance // -> no change in stack height } // end // else // begin // list.concat(taicpu.op_sym(a_new,current_asmdata.RefAsmSymbol(java_jubitset.jvm_full_typename(true),AT_METADATA))); // { the constructor doesn't return anything, so put a duplicate of the // self pointer on the evaluation stack for use as function result // after the constructor has run } // list.concat(taicpu.op_none(a_dup)); // thlcgjvm(hlcg).incstack(list,2); // { call the constructor } // sym:=tsym(java_jubitset.symtable.find('CREATE')); // if assigned(sym) and // (sym.typ=procsym) then // begin // pd:=tprocsym(sym).find_bytype_parameterless(potype_constructor); // if not assigned(pd) then // internalerror(2011062802); // end // else // internalerror(2011062803); // hlcg.a_call_name(list,pd,pd.mangledname,[],nil,false); // { duplicate self pointer is removed } // thlcgjvm(hlcg).decstack(list,1); // end; // { store reference to instance } // gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref); // thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0); // result:=true; // end; // procvardef: // begin // if not tprocvardef(def).is_addressonly then // begin // getimplicitobjtemp(list,tcpuprocvardef(def).classdef,temptype,ref); // result:=true; // end; // end; // stringdef: // begin // if is_shortstring(def) then // begin // gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref); // { add the maxlen parameter (s8inttype because parameters must // be sign extended) } // thlcgjvm(hlcg).a_load_const_stack(list,s8inttype,shortint(tstringdef(def).len),R_INTREGISTER); // { call the constructor } // sym:=tsym(tobjectdef(java_shortstring).symtable.find('CREATEEMPTY')); // if assigned(sym) and // (sym.typ=procsym) then // begin // if tprocsym(sym).procdeflist.Count<>1 then // internalerror(2011052404); // pd:=tprocdef(tprocsym(sym).procdeflist[0]); // hlcg.a_call_name(list,pd,pd.mangledname,[],nil,false); // end; // { static calls method replaces parameter with string instance // -> no change in stack height } // { store reference to instance } // thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0); // result:=true; // end; // end; // filedef: // begin // case tfiledef(def).filetyp of // ft_text: // result:=getifspecialtemp(list,search_system_type('TEXTREC').typedef,forcesize,temptype,ref); // ft_typed, // ft_untyped: // result:=getifspecialtemp(list,search_system_type('FILEREC').typedef,forcesize,temptype,ref); // end; // end; // else // ; // end; // end; procedure ttgwasm.alloctemp(list: TAsmList; size: asizeint; alignment: shortint; temptype: ttemptype; def: tdef; fini: boolean; out ref: treference); begin { the WebAssembly only supports 1 slot (= 4 bytes in FPC) and 2 slot (= 8 bytes in FPC) temps on the stack. double and int64 are 2 slots, the rest is one slot. There are no problems with reusing the same slot for a value of a different type. There are no alignment requirements either. } if size<4 then size:=4; if not(size in [4,8]) then internalerror(2010121401); { don't pass on "def", since we don't care if a slot is used again for a different type } inherited alloctemp(list, size shr 2, 1, temptype, nil, false, ref); end; constructor ttgwasm.create; begin inherited create; direction := 1; // temp variables are allocated as "locals", and it starts with 0 and goes beyond! end; procedure ttgwasm.setfirsttemp(l: asizeint); begin firsttemp:=l; lasttemp:=l; end; //procedure ttgwasm.getlocal(list: TAsmList; size: asizeint; alignment: shortint; def: tdef; var ref: treference); // begin // if not getifspecialtemp(list,def,size,tt_persistent,ref) then // inherited; // end; //procedure ttgjvm.gethltemp(list: TAsmList; def: tdef; forcesize: asizeint; temptype: ttemptype; out ref: treference); // begin // if not getifspecialtemp(list,def,forcesize,temptype,ref) then // inherited; // end; // //procedure ttgjvm.gethltempmanaged(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference); // begin // gethltemp(list,def,def.size,temptype,ref); // end; initialization tgobjclass:=ttgwasm; end.