{ 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, cpubase, symtype,tgobj; type { TWasmLocal } TWasmLocal = class inuse : Boolean; index : integer; typ : TWasmBasicType; next : TWasmLocal; // next in the same basic type nextseq : TWasmLocal; // from 0 to max constructor create(atype: TWasmBasicType; aindex: integer); end; { TWasmLocalVars } TWasmLocalVars = class private last: TWasmLocal; // need public? public locv: array[TWasmBasicType] of TWasmLocal; ordered: array of integer; first: TWasmLocal; // first in sequence varindex: integer; constructor Create(astartindex: Integer = 0); destructor Destroy; override; function alloc(bt: TWasmBasicType): integer; procedure dealloc(bt: TWasmBasicType; index: integer); procedure dealloc(index: integer); end; { ttgwasm } ttgwasm = class(ttgobj) private procedure updateFirstTemp; procedure allocLocalVarToRef(wbt: TWasmBasicType; out ref: treference); procedure LocalVarToRef(idx: integer; size: Integer; out ref: treference); protected procedure alloctemp(list: TAsmList; size: asizeint; alignment: shortint; temptype: ttemptype; def: tdef; fini: boolean; out ref: treference); override; public localvars: TWasmLocalVars; constructor create; override; destructor destroy; 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; procedure ungettemp(list: TAsmList; const ref : treference); override; end; function defToWasmBasic(def: tdef; var wbt: TWasmBasicType): Boolean; implementation uses verbose, cgbase, symconst,symtable,symdef,symsym,symcpu,defutil, aasmbase,aasmcpu, hlcgobj,hlcgcpu, procinfo; function defToWasmBasic(def: tdef; var wbt: TWasmBasicType): Boolean; begin Result := assigned(def); if not Result then Exit; if is_pointer(def) then wbt := wbt_i32 // wasm32 else if is_ordinal(def) then begin if is_64bit(def) then wbt := wbt_i64 else wbt := wbt_i32; end else if is_real(def) then begin if is_single(def) then wbt := wbt_f32 else wbt := wbt_f64; // real/double/extended end else Result := false; end; { TWasmLocal } constructor TWasmLocal.create(atype: TWasmBasicType; aindex: integer); begin typ:=atype; index:=aindex; end; { TWasmLocalVars } constructor TWasmLocalVars.Create(astartindex: Integer = 0); begin inherited Create; varindex := astartindex; end; destructor TWasmLocalVars.Destroy; var t : TWasmLocal; n : TWasmLocal; begin t := first; while Assigned(t) do begin n:=t; t:=t.nextseq; n.Free; end; inherited Destroy; end; { ttgwasm } procedure ttgwasm.alloctemp(list: TAsmList; size: asizeint; alignment: shortint; temptype: ttemptype; def: tdef; fini: boolean; out ref: treference); begin inherited; //Internalerror(2019091802); { 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); inherited alloctemp(list, size shr 2, 1, temptype, def, false, ref);} end; procedure ttgwasm.updateFirstTemp; begin firsttemp := localvars.varindex; if lasttemp index) do lc := lc.next; if Assigned(lc) then lc.inuse := false; end; procedure TWasmLocalVars.dealloc(index: integer); var lc : TWasmLocal; begin lc := first; while Assigned(lc) and (lc.index <> index) do lc := lc.nextseq; if Assigned(lc) then lc.inuse := false; end; initialization tgobjclass:=ttgwasm; end.