| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057 | {    Copyright (c) 1998-2002, 2021 by Florian Klaempfl and Nikolay Nikolov    Generate WebAssembly inline nodes    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 nwasminl;{$i fpcdefs.inc}interface    uses      node,ncginl,cpubase;    type      { twasminlinenode }      twasminlinenode = class(tcginlinenode)      private        function first_abs_real:tnode;override;        function first_int_real:tnode;override;        function first_sqrt_real:tnode;override;        function first_trunc_real:tnode;override;        function first_round_real:tnode;override;        function first_popcnt:tnode;override;        procedure second_abs_real;override;        procedure second_int_real;override;        procedure second_sqrt_real;override;        procedure second_trunc_real;override;        procedure second_round_real;override;        procedure second_high; override;        procedure second_popcnt;override;        procedure second_memory_size;        procedure second_memory_grow;        procedure second_memory_fill;        procedure second_memory_copy;        procedure second_unreachable;        procedure second_throw_fpcexception;        procedure second_atomic_fence;        procedure second_atomic_load(op: TAsmOp);        procedure second_atomic_store(op: TAsmOp);        procedure second_atomic_rmw_x_y(op: TAsmOp);        procedure second_atomic_rmw_x_y_z(op: TAsmOp);        procedure second_tls_get(const SymStr: string);      protected        function first_sqr_real: tnode; override;      public        function pass_typecheck_cpu: tnode; override;        function first_cpu: tnode; override;        procedure pass_generate_code_cpu; override;        procedure second_length;override;        procedure second_sqr_real; override;      end;implementation    uses      ninl,ncal,compinnr,      aasmbase,aasmdata,aasmcpu,      cgbase,cgutils,      hlcgobj,hlcgcpu,      defutil,pass_2,verbose,      symtype,symdef;{*****************************************************************************                               twasminlinenode*****************************************************************************}    function twasminlinenode.first_abs_real: tnode;      begin        expectloc:=LOC_FPUREGISTER;        result:=nil;      end;    function twasminlinenode.first_int_real: tnode;      begin        expectloc:=LOC_FPUREGISTER;        result:=nil;      end;    function twasminlinenode.first_sqrt_real: tnode;      begin        expectloc:=LOC_FPUREGISTER;        result:=nil;      end;    function twasminlinenode.first_trunc_real: tnode;      begin        expectloc:=LOC_REGISTER;        result:=nil;      end;    function twasminlinenode.first_round_real: tnode;      begin        expectloc:=LOC_REGISTER;        result:=nil;      end;    function twasminlinenode.first_popcnt: tnode;      begin        expectloc:=LOC_REGISTER;        result:=nil;      end;    procedure twasminlinenode.second_abs_real;      begin        secondpass(left);        hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);        thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);        case left.location.size of          OS_F32:            current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_f32_abs));          OS_F64:            current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_f64_abs));          else            internalerror(2021092902);        end;        location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));        location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);      end;    procedure twasminlinenode.second_int_real;      begin        secondpass(left);        hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);        thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);        case left.location.size of          OS_F32:            current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_f32_trunc));          OS_F64:            current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_f64_trunc));          else            internalerror(2021092903);        end;        location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));        location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);      end;    procedure twasminlinenode.second_sqrt_real;      begin        secondpass(left);        hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);        thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);        case left.location.size of          OS_F32:            current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_f32_sqrt));          OS_F64:            current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_f64_sqrt));          else            internalerror(2021092901);        end;        location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));        location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);      end;    procedure twasminlinenode.second_trunc_real;      begin        secondpass(left);        hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);        thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);        case left.location.size of          OS_F32:            current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_i64_trunc_f32_s));          OS_F64:            current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_i64_trunc_f64_s));          else            internalerror(2021092904);        end;        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));        location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);      end;    procedure twasminlinenode.second_round_real;      begin        secondpass(left);        hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);        thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);        case left.location.size of          OS_F32:            begin              current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_f32_nearest));              current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_i64_trunc_f32_s));            end;          OS_F64:            begin              current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_f64_nearest));              current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_i64_trunc_f64_s));            end          else            internalerror(2021092905);        end;        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));        location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);      end;    procedure twasminlinenode.second_high;      var        hightype: TWasmBasicType;      begin        secondpass(left);        if not(is_dynamic_array(left.resultdef)) then          Internalerror(2019122801);        { determine the WasmBasicType of the result }        if is_64bit(resultdef) then          hightype:=wbt_i64        else          hightype:=wbt_i32;        { length in dynamic arrays is at offset -sizeof(pint) }        thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);        { 64-bit pointer values need a <>0 comparison to produce a 32-bit int on the stack (0 or 1) for the 'if' instruction.          32-bit pointer values don't need it, because 'if' already expects and pops a 32-bit int and checks for <>0. }        if is_64bit(left.resultdef) then          begin            thlcgwasm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,left.resultdef,0,R_INTREGISTER);            thlcgwasm(hlcg).a_cmp_stack_stack(current_asmdata.CurrAsmList,left.resultdef,OC_NE);          end;        { if not nil }        current_asmdata.CurrAsmList.Concat(taicpu.op_functype(a_if,TWasmFuncType.Create([],[hightype])));        thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);        { volatility of the dyn. array refers to the volatility of the          string pointer, not of the string data }        thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);        { length in dynamic arrays is at offset -ossinttype.size }        thlcgwasm(hlcg).a_op_const_stack(current_asmdata.CurrAsmList,OP_SUB,left.resultdef,ossinttype.size);        { load length }        if ossinttype.size=8 then          current_asmdata.CurrAsmList.Concat(taicpu.op_const(a_i64_load,0))        else          current_asmdata.CurrAsmList.Concat(taicpu.op_const(a_i32_load,0));        { else }        current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_else));        thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);        { high=-1 }        thlcgwasm(hlcg).a_load_const_stack(current_asmdata.CurrAsmList,resultdef,-1,R_INTREGISTER);        { endif }        current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_end_if));        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));{$if not defined(cpu64bitalu) and not defined(cpuhighleveltarget)}        if location.size in [OS_64,OS_S64] then          begin            location.register64.reglo := cg.getintregister(current_asmdata.CurrAsmList,OS_32);            location.register64.reghi := cg.getintregister(current_asmdata.CurrAsmList,OS_32);          end        else{$endif}          location.register := hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);      end;    procedure twasminlinenode.second_popcnt;      begin        secondpass(left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,left.resultdef,left.location.register);        if is_64bit(left.resultdef) then          current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_i64_popcnt))        else          current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_i32_popcnt));        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));        location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);      end;    procedure twasminlinenode.second_memory_size;      begin        current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_memory_size));        thlcgwasm(hlcg).incstack(current_asmdata.CurrAsmList,1);        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));        location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);      end;    procedure twasminlinenode.second_memory_grow;      begin        secondpass(left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,left.resultdef,left.location.register);        current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_memory_grow));        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));        location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);      end;    procedure twasminlinenode.second_memory_fill;      begin        location_reset(location,LOC_VOID,OS_NO);        secondpass(tcallparanode(tcallparanode(tcallparanode(left).right).right).left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(tcallparanode(left).right).right).left.location,          tcallparanode(tcallparanode(tcallparanode(left).right).right).left.resultdef,          tcallparanode(tcallparanode(tcallparanode(left).right).right).left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(tcallparanode(left).right).right).left.resultdef,          tcallparanode(tcallparanode(tcallparanode(left).right).right).left.location.register);        secondpass(tcallparanode(tcallparanode(left).right).left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(left).right).left.location,          tcallparanode(tcallparanode(left).right).left.resultdef,          tcallparanode(tcallparanode(left).right).left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(left).right).left.resultdef,          tcallparanode(tcallparanode(left).right).left.location.register);        secondpass(tcallparanode(left).left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,          tcallparanode(left).left.location,          tcallparanode(left).left.resultdef,          tcallparanode(left).left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,          tcallparanode(left).left.resultdef,          tcallparanode(left).left.location.register);        current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_memory_fill));        thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,3);      end;    procedure twasminlinenode.second_memory_copy;      begin        location_reset(location,LOC_VOID,OS_NO);        secondpass(tcallparanode(tcallparanode(tcallparanode(left).right).right).left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(tcallparanode(left).right).right).left.location,          tcallparanode(tcallparanode(tcallparanode(left).right).right).left.resultdef,          tcallparanode(tcallparanode(tcallparanode(left).right).right).left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(tcallparanode(left).right).right).left.resultdef,          tcallparanode(tcallparanode(tcallparanode(left).right).right).left.location.register);        secondpass(tcallparanode(tcallparanode(left).right).left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(left).right).left.location,          tcallparanode(tcallparanode(left).right).left.resultdef,          tcallparanode(tcallparanode(left).right).left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(left).right).left.resultdef,          tcallparanode(tcallparanode(left).right).left.location.register);        secondpass(tcallparanode(left).left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,          tcallparanode(left).left.location,          tcallparanode(left).left.resultdef,          tcallparanode(left).left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,          tcallparanode(left).left.resultdef,          tcallparanode(left).left.location.register);        current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_memory_copy));        thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,3);      end;    procedure twasminlinenode.second_unreachable;      begin        location_reset(location,LOC_VOID,OS_NO);        current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_unreachable));      end;    procedure twasminlinenode.second_throw_fpcexception;      begin        location_reset(location,LOC_VOID,OS_NO);        current_asmdata.CurrAsmList.Concat(taicpu.op_sym(a_throw,current_asmdata.WeakRefAsmSymbol(FPC_EXCEPTION_TAG_SYM,AT_WASM_EXCEPTION_TAG)));      end;    procedure twasminlinenode.second_atomic_fence;      begin        location_reset(location,LOC_VOID,OS_NO);        current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_atomic_fence));      end;    procedure twasminlinenode.second_atomic_load(op: TAsmOp);      begin        secondpass(left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,left.resultdef,left.location.register);        current_asmdata.CurrAsmList.Concat(taicpu.op_const(op,0));        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));        location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);      end;    procedure twasminlinenode.second_atomic_store(op: TAsmOp);      begin        location_reset(location,LOC_VOID,OS_NO);        secondpass(tcallparanode(tcallparanode(left).right).left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(left).right).left.location,          tcallparanode(tcallparanode(left).right).left.resultdef,          tcallparanode(tcallparanode(left).right).left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(left).right).left.resultdef,          tcallparanode(tcallparanode(left).right).left.location.register);        secondpass(tcallparanode(left).left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,          tcallparanode(left).left.location,          tcallparanode(left).left.resultdef,          tcallparanode(left).left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,          tcallparanode(left).left.resultdef,          tcallparanode(left).left.location.register);        current_asmdata.CurrAsmList.Concat(taicpu.op_const(op,0));        thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,2);      end;    procedure twasminlinenode.second_atomic_rmw_x_y(op: TAsmOp);      begin        secondpass(tcallparanode(tcallparanode(left).right).left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(left).right).left.location,          tcallparanode(tcallparanode(left).right).left.resultdef,          tcallparanode(tcallparanode(left).right).left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(left).right).left.resultdef,          tcallparanode(tcallparanode(left).right).left.location.register);        secondpass(tcallparanode(left).left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,          tcallparanode(left).left.location,          tcallparanode(left).left.resultdef,          tcallparanode(left).left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,          tcallparanode(left).left.resultdef,          tcallparanode(left).left.location.register);        current_asmdata.CurrAsmList.Concat(taicpu.op_const(op,0));        thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));        location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);      end;    procedure twasminlinenode.second_atomic_rmw_x_y_z(op: TAsmOp);      begin        secondpass(tcallparanode(tcallparanode(tcallparanode(left).right).right).left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(tcallparanode(left).right).right).left.location,          tcallparanode(tcallparanode(tcallparanode(left).right).right).left.resultdef,          tcallparanode(tcallparanode(tcallparanode(left).right).right).left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(tcallparanode(left).right).right).left.resultdef,          tcallparanode(tcallparanode(tcallparanode(left).right).right).left.location.register);        secondpass(tcallparanode(tcallparanode(left).right).left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(left).right).left.location,          tcallparanode(tcallparanode(left).right).left.resultdef,          tcallparanode(tcallparanode(left).right).left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,          tcallparanode(tcallparanode(left).right).left.resultdef,          tcallparanode(tcallparanode(left).right).left.location.register);        secondpass(tcallparanode(left).left);        hlcg.location_force_reg(current_asmdata.CurrAsmList,          tcallparanode(left).left.location,          tcallparanode(left).left.resultdef,          tcallparanode(left).left.resultdef,false);        thlcgwasm(hlcg).a_load_reg_stack(current_asmdata.CurrAsmList,          tcallparanode(left).left.resultdef,          tcallparanode(left).left.location.register);        current_asmdata.CurrAsmList.Concat(taicpu.op_const(op,0));        thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,2);        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));        location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);      end;    procedure twasminlinenode.second_tls_get(const SymStr: string);      begin        current_asmdata.CurrAsmList.Concat(taicpu.op_sym(a_global_get,current_asmdata.RefAsmSymbol(SymStr,AT_WASM_GLOBAL)));        thlcgwasm(hlcg).incstack(current_asmdata.CurrAsmList,1);        location_reset(location,LOC_REGISTER,def_cgsize(resultdef));        location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);      end;    function twasminlinenode.first_sqr_real: tnode;      begin        expectloc:=LOC_FPUREGISTER;        first_sqr_real:=nil;      end;    function twasminlinenode.pass_typecheck_cpu: tnode;      begin        Result:=nil;        case inlinenumber of          in_wasm32_memory_size:            begin              CheckParameters(0);              resultdef:=u32inttype;            end;          in_wasm32_memory_grow:            begin              CheckParameters(1);              resultdef:=u32inttype;            end;          in_wasm32_unreachable:            begin              CheckParameters(0);              resultdef:=voidtype;            end;          in_wasm32_throw_fpcexception:            begin              CheckParameters(0);              resultdef:=voidtype;            end;          in_wasm32_memory_fill:            begin              CheckParameters(3);              resultdef:=voidtype;            end;          in_wasm32_memory_copy:            begin              CheckParameters(3);              resultdef:=voidtype;            end;          in_wasm32_atomic_fence:            begin              CheckParameters(0);              resultdef:=voidtype;            end;          in_wasm32_i32_atomic_rmw8_add_u,          in_wasm32_i32_atomic_rmw16_add_u,          in_wasm32_i32_atomic_rmw_add,          in_wasm32_i32_atomic_rmw8_sub_u,          in_wasm32_i32_atomic_rmw16_sub_u,          in_wasm32_i32_atomic_rmw_sub,          in_wasm32_i32_atomic_rmw8_and_u,          in_wasm32_i32_atomic_rmw16_and_u,          in_wasm32_i32_atomic_rmw_and,          in_wasm32_i32_atomic_rmw8_or_u,          in_wasm32_i32_atomic_rmw16_or_u,          in_wasm32_i32_atomic_rmw_or,          in_wasm32_i32_atomic_rmw8_xor_u,          in_wasm32_i32_atomic_rmw16_xor_u,          in_wasm32_i32_atomic_rmw_xor,          in_wasm32_i32_atomic_rmw8_xchg_u,          in_wasm32_i32_atomic_rmw16_xchg_u,          in_wasm32_i32_atomic_rmw_xchg:            begin              CheckParameters(2);              resultdef:=u32inttype;            end;          in_wasm32_i64_atomic_rmw8_add_u,          in_wasm32_i64_atomic_rmw16_add_u,          in_wasm32_i64_atomic_rmw32_add_u,          in_wasm32_i64_atomic_rmw_add,          in_wasm32_i64_atomic_rmw8_sub_u,          in_wasm32_i64_atomic_rmw16_sub_u,          in_wasm32_i64_atomic_rmw32_sub_u,          in_wasm32_i64_atomic_rmw_sub,          in_wasm32_i64_atomic_rmw8_and_u,          in_wasm32_i64_atomic_rmw16_and_u,          in_wasm32_i64_atomic_rmw32_and_u,          in_wasm32_i64_atomic_rmw_and,          in_wasm32_i64_atomic_rmw8_or_u,          in_wasm32_i64_atomic_rmw16_or_u,          in_wasm32_i64_atomic_rmw32_or_u,          in_wasm32_i64_atomic_rmw_or,          in_wasm32_i64_atomic_rmw8_xor_u,          in_wasm32_i64_atomic_rmw16_xor_u,          in_wasm32_i64_atomic_rmw32_xor_u,          in_wasm32_i64_atomic_rmw_xor,          in_wasm32_i64_atomic_rmw8_xchg_u,          in_wasm32_i64_atomic_rmw16_xchg_u,          in_wasm32_i64_atomic_rmw32_xchg_u,          in_wasm32_i64_atomic_rmw_xchg:            begin              CheckParameters(2);              resultdef:=u64inttype;            end;          in_wasm32_i32_atomic_rmw8_cmpxchg_u,          in_wasm32_i32_atomic_rmw16_cmpxchg_u,          in_wasm32_i32_atomic_rmw_cmpxchg:            begin              CheckParameters(3);              resultdef:=u32inttype;            end;          in_wasm32_i64_atomic_rmw8_cmpxchg_u,          in_wasm32_i64_atomic_rmw16_cmpxchg_u,          in_wasm32_i64_atomic_rmw32_cmpxchg_u,          in_wasm32_i64_atomic_rmw_cmpxchg:            begin              CheckParameters(3);              resultdef:=u64inttype;            end;          in_wasm32_memory_atomic_wait32,          in_wasm32_memory_atomic_wait64:            begin              CheckParameters(3);              resultdef:=s32inttype;            end;          in_wasm32_memory_atomic_notify:            begin              CheckParameters(2);              resultdef:=u32inttype;            end;          in_i32_atomic_load8_u,          in_i32_atomic_load16_u,          in_i32_atomic_load:            begin              CheckParameters(1);              resultdef:=u32inttype;            end;          in_i64_atomic_load8_u,          in_i64_atomic_load16_u,          in_i64_atomic_load32_u,          in_i64_atomic_load:            begin              CheckParameters(1);              resultdef:=u64inttype;            end;          in_i32_atomic_store8,          in_i32_atomic_store16,          in_i32_atomic_store,          in_i64_atomic_store8,          in_i64_atomic_store16,          in_i64_atomic_store32,          in_i64_atomic_store:            begin              CheckParameters(2);              resultdef:=voidtype;            end;          in_wasm32_tls_size,          in_wasm32_tls_align:            begin              CheckParameters(0);              resultdef:=u32inttype;            end;          in_wasm32_tls_base:            begin              CheckParameters(0);              resultdef:=voidpointertype;            end;          else            Result:=inherited pass_typecheck_cpu;        end;      end;    function twasminlinenode.first_cpu: tnode;      begin        Result:=nil;        case inlinenumber of          in_wasm32_memory_size,          in_wasm32_memory_grow:            expectloc:=LOC_REGISTER;          in_wasm32_memory_fill,          in_wasm32_memory_copy,          in_wasm32_unreachable,          in_wasm32_throw_fpcexception,          in_wasm32_atomic_fence,          in_i32_atomic_store8,          in_i32_atomic_store16,          in_i32_atomic_store,          in_i64_atomic_store8,          in_i64_atomic_store16,          in_i64_atomic_store32,          in_i64_atomic_store:            expectloc:=LOC_VOID;          in_wasm32_i32_atomic_rmw8_add_u,          in_wasm32_i32_atomic_rmw16_add_u,          in_wasm32_i32_atomic_rmw_add,          in_wasm32_i64_atomic_rmw8_add_u,          in_wasm32_i64_atomic_rmw16_add_u,          in_wasm32_i64_atomic_rmw32_add_u,          in_wasm32_i64_atomic_rmw_add,          in_wasm32_i32_atomic_rmw8_sub_u,          in_wasm32_i32_atomic_rmw16_sub_u,          in_wasm32_i32_atomic_rmw_sub,          in_wasm32_i64_atomic_rmw8_sub_u,          in_wasm32_i64_atomic_rmw16_sub_u,          in_wasm32_i64_atomic_rmw32_sub_u,          in_wasm32_i64_atomic_rmw_sub,          in_wasm32_i32_atomic_rmw8_and_u,          in_wasm32_i32_atomic_rmw16_and_u,          in_wasm32_i32_atomic_rmw_and,          in_wasm32_i64_atomic_rmw8_and_u,          in_wasm32_i64_atomic_rmw16_and_u,          in_wasm32_i64_atomic_rmw32_and_u,          in_wasm32_i64_atomic_rmw_and,          in_wasm32_i32_atomic_rmw8_or_u,          in_wasm32_i32_atomic_rmw16_or_u,          in_wasm32_i32_atomic_rmw_or,          in_wasm32_i64_atomic_rmw8_or_u,          in_wasm32_i64_atomic_rmw16_or_u,          in_wasm32_i64_atomic_rmw32_or_u,          in_wasm32_i64_atomic_rmw_or,          in_wasm32_i32_atomic_rmw8_xor_u,          in_wasm32_i32_atomic_rmw16_xor_u,          in_wasm32_i32_atomic_rmw_xor,          in_wasm32_i64_atomic_rmw8_xor_u,          in_wasm32_i64_atomic_rmw16_xor_u,          in_wasm32_i64_atomic_rmw32_xor_u,          in_wasm32_i64_atomic_rmw_xor,          in_wasm32_i32_atomic_rmw8_xchg_u,          in_wasm32_i32_atomic_rmw16_xchg_u,          in_wasm32_i32_atomic_rmw_xchg,          in_wasm32_i64_atomic_rmw8_xchg_u,          in_wasm32_i64_atomic_rmw16_xchg_u,          in_wasm32_i64_atomic_rmw32_xchg_u,          in_wasm32_i64_atomic_rmw_xchg,          in_wasm32_i32_atomic_rmw8_cmpxchg_u,          in_wasm32_i32_atomic_rmw16_cmpxchg_u,          in_wasm32_i32_atomic_rmw_cmpxchg,          in_wasm32_i64_atomic_rmw8_cmpxchg_u,          in_wasm32_i64_atomic_rmw16_cmpxchg_u,          in_wasm32_i64_atomic_rmw32_cmpxchg_u,          in_wasm32_i64_atomic_rmw_cmpxchg,          in_wasm32_memory_atomic_wait32,          in_wasm32_memory_atomic_wait64,          in_wasm32_memory_atomic_notify,          in_i32_atomic_load8_u,          in_i32_atomic_load16_u,          in_i32_atomic_load,          in_i64_atomic_load8_u,          in_i64_atomic_load16_u,          in_i64_atomic_load32_u,          in_i64_atomic_load,          in_wasm32_tls_size,          in_wasm32_tls_align,          in_wasm32_tls_base:            expectloc:=LOC_REGISTER;          else            Result:=inherited first_cpu;        end;      end;    procedure twasminlinenode.pass_generate_code_cpu;      begin        case inlinenumber of          in_wasm32_memory_size:            second_memory_size;          in_wasm32_memory_grow:            second_memory_grow;          in_wasm32_memory_fill:            second_memory_fill;          in_wasm32_memory_copy:            second_memory_copy;          in_wasm32_unreachable:            second_unreachable;          in_wasm32_throw_fpcexception:            second_throw_fpcexception;          in_wasm32_atomic_fence:            second_atomic_fence;          in_wasm32_i32_atomic_rmw8_add_u:            second_atomic_rmw_x_y(a_i32_atomic_rmw8_add_u);          in_wasm32_i32_atomic_rmw16_add_u:            second_atomic_rmw_x_y(a_i32_atomic_rmw16_add_u);          in_wasm32_i32_atomic_rmw_add:            second_atomic_rmw_x_y(a_i32_atomic_rmw_add);          in_wasm32_i64_atomic_rmw8_add_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw8_add_u);          in_wasm32_i64_atomic_rmw16_add_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw16_add_u);          in_wasm32_i64_atomic_rmw32_add_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw32_add_u);          in_wasm32_i64_atomic_rmw_add:            second_atomic_rmw_x_y(a_i64_atomic_rmw_add);          in_wasm32_i32_atomic_rmw8_sub_u:            second_atomic_rmw_x_y(a_i32_atomic_rmw8_sub_u);          in_wasm32_i32_atomic_rmw16_sub_u:            second_atomic_rmw_x_y(a_i32_atomic_rmw16_sub_u);          in_wasm32_i32_atomic_rmw_sub:            second_atomic_rmw_x_y(a_i32_atomic_rmw_sub);          in_wasm32_i64_atomic_rmw8_sub_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw8_sub_u);          in_wasm32_i64_atomic_rmw16_sub_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw16_sub_u);          in_wasm32_i64_atomic_rmw32_sub_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw32_sub_u);          in_wasm32_i64_atomic_rmw_sub:            second_atomic_rmw_x_y(a_i64_atomic_rmw_sub);          in_wasm32_i32_atomic_rmw8_and_u:            second_atomic_rmw_x_y(a_i32_atomic_rmw8_and_u);          in_wasm32_i32_atomic_rmw16_and_u:            second_atomic_rmw_x_y(a_i32_atomic_rmw16_and_u);          in_wasm32_i32_atomic_rmw_and:            second_atomic_rmw_x_y(a_i32_atomic_rmw_and);          in_wasm32_i64_atomic_rmw8_and_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw8_and_u);          in_wasm32_i64_atomic_rmw16_and_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw16_and_u);          in_wasm32_i64_atomic_rmw32_and_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw32_and_u);          in_wasm32_i64_atomic_rmw_and:            second_atomic_rmw_x_y(a_i64_atomic_rmw_and);          in_wasm32_i32_atomic_rmw8_or_u:            second_atomic_rmw_x_y(a_i32_atomic_rmw8_or_u);          in_wasm32_i32_atomic_rmw16_or_u:            second_atomic_rmw_x_y(a_i32_atomic_rmw16_or_u);          in_wasm32_i32_atomic_rmw_or:            second_atomic_rmw_x_y(a_i32_atomic_rmw_or);          in_wasm32_i64_atomic_rmw8_or_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw8_or_u);          in_wasm32_i64_atomic_rmw16_or_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw16_or_u);          in_wasm32_i64_atomic_rmw32_or_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw32_or_u);          in_wasm32_i64_atomic_rmw_or:            second_atomic_rmw_x_y(a_i64_atomic_rmw_or);          in_wasm32_i32_atomic_rmw8_xor_u:            second_atomic_rmw_x_y(a_i32_atomic_rmw8_xor_u);          in_wasm32_i32_atomic_rmw16_xor_u:            second_atomic_rmw_x_y(a_i32_atomic_rmw16_xor_u);          in_wasm32_i32_atomic_rmw_xor:            second_atomic_rmw_x_y(a_i32_atomic_rmw_xor);          in_wasm32_i64_atomic_rmw8_xor_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw8_xor_u);          in_wasm32_i64_atomic_rmw16_xor_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw16_xor_u);          in_wasm32_i64_atomic_rmw32_xor_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw32_xor_u);          in_wasm32_i64_atomic_rmw_xor:            second_atomic_rmw_x_y(a_i64_atomic_rmw_xor);          in_wasm32_i32_atomic_rmw8_xchg_u:            second_atomic_rmw_x_y(a_i32_atomic_rmw8_xchg_u);          in_wasm32_i32_atomic_rmw16_xchg_u:            second_atomic_rmw_x_y(a_i32_atomic_rmw16_xchg_u);          in_wasm32_i32_atomic_rmw_xchg:            second_atomic_rmw_x_y(a_i32_atomic_rmw_xchg);          in_wasm32_i64_atomic_rmw8_xchg_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw8_xchg_u);          in_wasm32_i64_atomic_rmw16_xchg_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw16_xchg_u);          in_wasm32_i64_atomic_rmw32_xchg_u:            second_atomic_rmw_x_y(a_i64_atomic_rmw32_xchg_u);          in_wasm32_i64_atomic_rmw_xchg:            second_atomic_rmw_x_y(a_i64_atomic_rmw_xchg);          in_wasm32_i32_atomic_rmw8_cmpxchg_u:            second_atomic_rmw_x_y_z(a_i32_atomic_rmw8_cmpxchg_u);          in_wasm32_i32_atomic_rmw16_cmpxchg_u:            second_atomic_rmw_x_y_z(a_i32_atomic_rmw16_cmpxchg_u);          in_wasm32_i32_atomic_rmw_cmpxchg:            second_atomic_rmw_x_y_z(a_i32_atomic_rmw_cmpxchg);          in_wasm32_i64_atomic_rmw8_cmpxchg_u:            second_atomic_rmw_x_y_z(a_i64_atomic_rmw8_cmpxchg_u);          in_wasm32_i64_atomic_rmw16_cmpxchg_u:            second_atomic_rmw_x_y_z(a_i64_atomic_rmw16_cmpxchg_u);          in_wasm32_i64_atomic_rmw32_cmpxchg_u:            second_atomic_rmw_x_y_z(a_i64_atomic_rmw32_cmpxchg_u);          in_wasm32_i64_atomic_rmw_cmpxchg:            second_atomic_rmw_x_y_z(a_i64_atomic_rmw_cmpxchg);          in_wasm32_memory_atomic_wait32:            second_atomic_rmw_x_y_z(a_memory_atomic_wait32);          in_wasm32_memory_atomic_wait64:            second_atomic_rmw_x_y_z(a_memory_atomic_wait64);          in_wasm32_memory_atomic_notify:            second_atomic_rmw_x_y(a_memory_atomic_notify);          in_i32_atomic_load8_u:            second_atomic_load(a_i32_atomic_load8_u);          in_i32_atomic_load16_u:            second_atomic_load(a_i32_atomic_load16_u);          in_i32_atomic_load:            second_atomic_load(a_i32_atomic_load);          in_i64_atomic_load8_u:            second_atomic_load(a_i64_atomic_load8_u);          in_i64_atomic_load16_u:            second_atomic_load(a_i64_atomic_load16_u);          in_i64_atomic_load32_u:            second_atomic_load(a_i64_atomic_load32_u);          in_i64_atomic_load:            second_atomic_load(a_i64_atomic_load);          in_i32_atomic_store8:            second_atomic_store(a_i32_atomic_store8);          in_i32_atomic_store16:            second_atomic_store(a_i32_atomic_store16);          in_i32_atomic_store:            second_atomic_store(a_i32_atomic_store);          in_i64_atomic_store8:            second_atomic_store(a_i64_atomic_store8);          in_i64_atomic_store16:            second_atomic_store(a_i64_atomic_store16);          in_i64_atomic_store32:            second_atomic_store(a_i64_atomic_store32);          in_i64_atomic_store:            second_atomic_store(a_i64_atomic_store);          in_wasm32_tls_size:            second_tls_get(TLS_SIZE_SYM);          in_wasm32_tls_align:            second_tls_get(TLS_ALIGN_SYM);          in_wasm32_tls_base:            second_tls_get(TLS_BASE_SYM);          else            inherited pass_generate_code_cpu;        end;      end;    procedure twasminlinenode.second_length;      var        lendef : tdef;        href : treference;        extra_slots: LongInt;      begin        secondpass(left);        if is_shortstring(left.resultdef) then          begin            location_copy(location,left.location);            location.size:=OS_8;          end        else          begin            { length in ansi/wide strings and high in dynamic arrays is at offset -sizeof(pint) }            hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,left.resultdef,false);            thlcgwasm(hlcg).a_cmp_const_reg_stack(current_asmdata.CurrAsmList,left.resultdef,OC_EQ,0,left.location.register);            current_asmdata.CurrAsmList.Concat(taicpu.op_functype(a_if,TWasmFuncType.Create([],[wbt_i32])));            thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);            current_asmdata.CurrAsmList.Concat(taicpu.op_const(a_i32_const,0));            thlcgwasm(hlcg).incstack(current_asmdata.CurrAsmList,1);            current_asmdata.CurrAsmList.Concat( taicpu.op_none(a_else) );            thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);            { the length of a widestring is a 32 bit unsigned int. Since every              character occupies 2 bytes, on a 32 bit platform you can express              the maximum length using 31 bits. On a 64 bit platform, it may be              32 bits. This means that regardless of the platform, a location              with size OS_SINT/ossinttype can hold the length without              overflowing (this code returns an ossinttype value) }            if is_widestring(left.resultdef) then              lendef:=u32inttype            else              lendef:=ossinttype;            { volatility of the ansistring/widestring refers to the volatility of the              string pointer, not of the string data }            hlcg.reference_reset_base(href,left.resultdef,left.location.register,-lendef.size,ctempposinvalid,lendef.alignment,[]);            extra_slots:=thlcgwasm(hlcg).prepare_stack_for_ref(current_asmdata.CurrAsmList,href,false);            thlcgwasm(hlcg).a_load_ref_stack(current_asmdata.CurrAsmList,lendef,href,extra_slots);            if is_widestring(left.resultdef) then              thlcgwasm(hlcg).a_op_const_stack(current_asmdata.CurrAsmList,OP_SHR,resultdef,1);            { Dynamic arrays do not have their length attached but their maximum index }            if is_dynamic_array(left.resultdef) then              thlcgwasm(hlcg).a_op_const_stack(current_asmdata.CurrAsmList,OP_ADD,resultdef,1);            current_asmdata.CurrAsmList.Concat( taicpu.op_none(a_end_if) );            location_reset(location,LOC_REGISTER,def_cgsize(resultdef));            location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);            thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);          end;      end;    procedure twasminlinenode.second_sqr_real;      begin        secondpass(left);        hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);        thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);        thlcgwasm(hlcg).a_load_loc_stack(current_asmdata.CurrAsmList,left.resultdef,left.location);        case left.location.size of          OS_F32:            current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_f32_mul));          OS_F64:            current_asmdata.CurrAsmList.Concat(taicpu.op_none(a_f64_mul));          else            internalerror(2021060102);        end;        thlcgwasm(hlcg).decstack(current_asmdata.CurrAsmList,1);        location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));        location.register:=hlcg.getregisterfordef(current_asmdata.CurrAsmList,resultdef);        thlcgwasm(hlcg).a_load_stack_loc(current_asmdata.CurrAsmList,resultdef,location);      end;begin  cinlinenode:=twasminlinenode;end.
 |