tgcpu.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. {
  2. Copyright (C) 2019 Dmitry Boyarintsev
  3. This unit handles the temporary variables for the WebAssembly
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit tgcpu;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. aasmdata,
  23. cgutils,
  24. symtype,tgobj;
  25. type
  26. { ttgwasm }
  27. ttgwasm = class(ttgobj)
  28. //protected
  29. // procedure getimplicitobjtemp(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference);
  30. // function getifspecialtemp(list: TAsmList; def: tdef; forcesize: asizeint; temptype: ttemptype; out ref: treference): boolean;
  31. procedure alloctemp(list: TAsmList; size: asizeint; alignment: shortint; temptype: ttemptype; def: tdef; fini: boolean; out ref: treference); override;
  32. public
  33. constructor create; override;
  34. procedure setfirsttemp(l : asizeint); override;
  35. //procedure getlocal(list: TAsmList; size: asizeint; alignment: shortint; def: tdef; var ref: treference); override;
  36. //procedure gethltemp(list: TAsmList; def: tdef; forcesize: asizeint; temptype: ttemptype; out ref: treference); override;
  37. //procedure gethltempmanaged(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference); override;
  38. end;
  39. implementation
  40. uses
  41. verbose,
  42. cgbase,
  43. symconst,symtable,symdef,symsym,symcpu,defutil,
  44. cpubase,aasmbase,aasmcpu,
  45. hlcgobj,hlcgcpu;
  46. { ttgwasm }
  47. //procedure ttgwasm.getimplicitobjtemp(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference);
  48. // var
  49. // sym: tsym;
  50. // pd: tprocdef;
  51. // begin
  52. // gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref);
  53. // list.concat(taicpu.op_sym(a_new,current_asmdata.RefAsmSymbol(tabstractrecorddef(def).jvm_full_typename(true),AT_METADATA)));
  54. // { the constructor doesn't return anything, so put a duplicate of the
  55. // self pointer on the evaluation stack for use as function result
  56. // after the constructor has run }
  57. // list.concat(taicpu.op_none(a_dup));
  58. // thlcgjvm(hlcg).incstack(list,2);
  59. // { call the constructor }
  60. // sym:=tsym(tabstractrecorddef(def).symtable.find('CREATE'));
  61. // if assigned(sym) and
  62. // (sym.typ=procsym) then
  63. // begin
  64. // pd:=tprocsym(sym).find_bytype_parameterless(potype_constructor);
  65. // if not assigned(pd) then
  66. // internalerror(2011032701);
  67. // end
  68. // else
  69. // internalerror(2011060301);
  70. // hlcg.a_call_name(list,pd,pd.mangledname,[],nil,false);
  71. // thlcgjvm(hlcg).decstack(list,1);
  72. // { store reference to instance }
  73. // thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0);
  74. // end;
  75. //function ttgwasm.getifspecialtemp(list: TAsmList; def: tdef; forcesize: asizeint; temptype: ttemptype; out ref: treference): boolean;
  76. // var
  77. // eledef: tdef;
  78. // ndim: longint;
  79. // sym: tsym;
  80. // pd: tprocdef;
  81. // begin
  82. // result:=false;
  83. // case def.typ of
  84. // arraydef:
  85. // begin
  86. // if not is_dynamic_array(def) then
  87. // begin
  88. // { allocate an array of the right size }
  89. // gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref);
  90. // ndim:=0;
  91. // eledef:=def;
  92. // repeat
  93. // if forcesize<>-1 then
  94. // thlcgjvm(hlcg).a_load_const_stack(list,s32inttype,forcesize div tarraydef(eledef).elesize,R_INTREGISTER)
  95. // else
  96. // thlcgjvm(hlcg).a_load_const_stack(list,s32inttype,tarraydef(eledef).elecount,R_INTREGISTER);
  97. // eledef:=tarraydef(eledef).elementdef;
  98. // inc(ndim);
  99. // forcesize:=-1;
  100. // until (eledef.typ<>arraydef) or
  101. // is_dynamic_array(eledef);
  102. // eledef:=tarraydef(def).elementdef;
  103. // thlcgjvm(hlcg).g_newarray(list,def,ndim);
  104. // thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0);
  105. // result:=true;
  106. // end;
  107. // end;
  108. // recorddef:
  109. // begin
  110. // getimplicitobjtemp(list,def,temptype,ref);
  111. // result:=true;
  112. // end;
  113. // setdef:
  114. // begin
  115. // if tsetdef(def).elementdef.typ=enumdef then
  116. // begin
  117. // { load enum class type }
  118. // list.concat(taicpu.op_sym(a_ldc,current_asmdata.RefAsmSymbol(tcpuenumdef(tenumdef(tsetdef(def).elementdef).getbasedef).classdef.jvm_full_typename(true),AT_METADATA)));
  119. // thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1);
  120. // { call tenumset.noneOf() class method }
  121. // sym:=tsym(tobjectdef(java_juenumset).symtable.find('NONEOF'));
  122. // if assigned(sym) and
  123. // (sym.typ=procsym) then
  124. // begin
  125. // if tprocsym(sym).procdeflist.Count<>1 then
  126. // internalerror(2011062801);
  127. // pd:=tprocdef(tprocsym(sym).procdeflist[0]);
  128. // hlcg.a_call_name(list,pd,pd.mangledname,[],nil,false);
  129. // end;
  130. // { static calls method replaces parameter with set instance
  131. // -> no change in stack height }
  132. // end
  133. // else
  134. // begin
  135. // list.concat(taicpu.op_sym(a_new,current_asmdata.RefAsmSymbol(java_jubitset.jvm_full_typename(true),AT_METADATA)));
  136. // { the constructor doesn't return anything, so put a duplicate of the
  137. // self pointer on the evaluation stack for use as function result
  138. // after the constructor has run }
  139. // list.concat(taicpu.op_none(a_dup));
  140. // thlcgjvm(hlcg).incstack(list,2);
  141. // { call the constructor }
  142. // sym:=tsym(java_jubitset.symtable.find('CREATE'));
  143. // if assigned(sym) and
  144. // (sym.typ=procsym) then
  145. // begin
  146. // pd:=tprocsym(sym).find_bytype_parameterless(potype_constructor);
  147. // if not assigned(pd) then
  148. // internalerror(2011062802);
  149. // end
  150. // else
  151. // internalerror(2011062803);
  152. // hlcg.a_call_name(list,pd,pd.mangledname,[],nil,false);
  153. // { duplicate self pointer is removed }
  154. // thlcgjvm(hlcg).decstack(list,1);
  155. // end;
  156. // { store reference to instance }
  157. // gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref);
  158. // thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0);
  159. // result:=true;
  160. // end;
  161. // procvardef:
  162. // begin
  163. // if not tprocvardef(def).is_addressonly then
  164. // begin
  165. // getimplicitobjtemp(list,tcpuprocvardef(def).classdef,temptype,ref);
  166. // result:=true;
  167. // end;
  168. // end;
  169. // stringdef:
  170. // begin
  171. // if is_shortstring(def) then
  172. // begin
  173. // gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref);
  174. // { add the maxlen parameter (s8inttype because parameters must
  175. // be sign extended) }
  176. // thlcgjvm(hlcg).a_load_const_stack(list,s8inttype,shortint(tstringdef(def).len),R_INTREGISTER);
  177. // { call the constructor }
  178. // sym:=tsym(tobjectdef(java_shortstring).symtable.find('CREATEEMPTY'));
  179. // if assigned(sym) and
  180. // (sym.typ=procsym) then
  181. // begin
  182. // if tprocsym(sym).procdeflist.Count<>1 then
  183. // internalerror(2011052404);
  184. // pd:=tprocdef(tprocsym(sym).procdeflist[0]);
  185. // hlcg.a_call_name(list,pd,pd.mangledname,[],nil,false);
  186. // end;
  187. // { static calls method replaces parameter with string instance
  188. // -> no change in stack height }
  189. // { store reference to instance }
  190. // thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0);
  191. // result:=true;
  192. // end;
  193. // end;
  194. // filedef:
  195. // begin
  196. // case tfiledef(def).filetyp of
  197. // ft_text:
  198. // result:=getifspecialtemp(list,search_system_type('TEXTREC').typedef,forcesize,temptype,ref);
  199. // ft_typed,
  200. // ft_untyped:
  201. // result:=getifspecialtemp(list,search_system_type('FILEREC').typedef,forcesize,temptype,ref);
  202. // end;
  203. // end;
  204. // else
  205. // ;
  206. // end;
  207. // end;
  208. procedure ttgwasm.alloctemp(list: TAsmList; size: asizeint; alignment: shortint; temptype: ttemptype; def: tdef; fini: boolean; out ref: treference);
  209. begin
  210. { the WebAssembly only supports 1 slot (= 4 bytes in FPC) and 2 slot (= 8 bytes in
  211. FPC) temps on the stack. double and int64 are 2 slots, the rest is one slot.
  212. There are no problems with reusing the same slot for a value of a different
  213. type. There are no alignment requirements either. }
  214. if size<4 then
  215. size:=4;
  216. if not(size in [4,8]) then
  217. internalerror(2010121401);
  218. { don't pass on "def", since we don't care if a slot is used again for a
  219. different type }
  220. inherited alloctemp(list, size shr 2, 1, temptype, nil, false, ref);
  221. end;
  222. constructor ttgwasm.create;
  223. begin
  224. inherited create;
  225. direction := 1; // temp variables are allocated as "locals", and it starts with 0 and goes beyond!
  226. end;
  227. procedure ttgwasm.setfirsttemp(l: asizeint);
  228. begin
  229. firsttemp:=l;
  230. lasttemp:=l;
  231. end;
  232. //procedure ttgwasm.getlocal(list: TAsmList; size: asizeint; alignment: shortint; def: tdef; var ref: treference);
  233. // begin
  234. // if not getifspecialtemp(list,def,size,tt_persistent,ref) then
  235. // inherited;
  236. // end;
  237. //procedure ttgjvm.gethltemp(list: TAsmList; def: tdef; forcesize: asizeint; temptype: ttemptype; out ref: treference);
  238. // begin
  239. // if not getifspecialtemp(list,def,forcesize,temptype,ref) then
  240. // inherited;
  241. // end;
  242. //
  243. //procedure ttgjvm.gethltempmanaged(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference);
  244. // begin
  245. // gethltemp(list,def,def.size,temptype,ref);
  246. // end;
  247. initialization
  248. tgobjclass:=ttgwasm;
  249. end.