tgcpu.pas 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. {
  2. Copyright (C) 2010 by Jonas Maebe
  3. This unit handles the temporary variables for the JVM
  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. {
  18. This unit handles the temporary variables for the JVM.
  19. }
  20. unit tgcpu;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. globtype,
  25. aasmdata,
  26. cgutils,
  27. symtype,tgobj;
  28. type
  29. { ttgjvm }
  30. ttgjvm = class(ttgobj)
  31. protected
  32. procedure getimplicitobjtemp(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference);
  33. function getifspecialtemp(list: TAsmList; def: tdef; forcesize: aint; temptype: ttemptype; out ref: treference): boolean;
  34. function alloctemp(list: TAsmList; size, alignment: longint; temptype: ttemptype; def: tdef): longint; override;
  35. public
  36. procedure setfirsttemp(l : longint); override;
  37. procedure getlocal(list: TAsmList; size: longint; alignment: shortint; def: tdef; var ref: treference); override;
  38. procedure gethltemp(list: TAsmList; def: tdef; forcesize: aint; temptype: ttemptype; out ref: treference); override;
  39. procedure gethltemptyped(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference); override;
  40. end;
  41. implementation
  42. uses
  43. verbose,
  44. cgbase,
  45. symconst,symdef,symsym,defutil,
  46. cpubase,aasmcpu,
  47. hlcgobj,hlcgcpu;
  48. { ttgjvm }
  49. procedure ttgjvm.getimplicitobjtemp(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference);
  50. var
  51. sym: tsym;
  52. pd: tprocdef;
  53. begin
  54. gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref);
  55. list.concat(taicpu.op_sym(a_new,current_asmdata.RefAsmSymbol(tabstractrecorddef(def).jvm_full_typename(true))));
  56. { the constructor doesn't return anything, so put a duplicate of the
  57. self pointer on the evaluation stack for use as function result
  58. after the constructor has run }
  59. list.concat(taicpu.op_none(a_dup));
  60. thlcgjvm(hlcg).incstack(list,2);
  61. { call the constructor }
  62. sym:=tsym(tabstractrecorddef(def).symtable.find('CREATE'));
  63. if assigned(sym) and
  64. (sym.typ=procsym) then
  65. begin
  66. pd:=tprocsym(sym).find_bytype_parameterless(potype_constructor);
  67. if not assigned(pd) then
  68. internalerror(2011032701);
  69. end
  70. else
  71. internalerror(2011060301);
  72. hlcg.a_call_name(list,pd,pd.mangledname,false);
  73. thlcgjvm(hlcg).decstack(list,1);
  74. { store reference to instance }
  75. thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0);
  76. end;
  77. function ttgjvm.getifspecialtemp(list: TAsmList; def: tdef; forcesize: aint; temptype: ttemptype; out ref: treference): boolean;
  78. var
  79. eledef: tdef;
  80. ndim: longint;
  81. sym: tsym;
  82. pd: tprocdef;
  83. begin
  84. result:=false;
  85. case def.typ of
  86. arraydef:
  87. begin
  88. if not is_dynamic_array(def) then
  89. begin
  90. { allocate an array of the right size }
  91. gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref);
  92. ndim:=0;
  93. eledef:=def;
  94. repeat
  95. if forcesize<>-1 then
  96. thlcgjvm(hlcg).a_load_const_stack(list,s32inttype,forcesize div tarraydef(eledef).elesize,R_INTREGISTER)
  97. else
  98. thlcgjvm(hlcg).a_load_const_stack(list,s32inttype,tarraydef(eledef).elecount,R_INTREGISTER);
  99. eledef:=tarraydef(eledef).elementdef;
  100. inc(ndim);
  101. forcesize:=-1;
  102. until (eledef.typ<>arraydef) or
  103. is_dynamic_array(eledef);
  104. eledef:=tarraydef(def).elementdef;
  105. thlcgjvm(hlcg).g_newarray(list,def,ndim);
  106. thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0);
  107. { allocate the records }
  108. if is_record(eledef) then
  109. hlcg.g_initialize(list,def,ref);
  110. result:=true;
  111. end;
  112. end;
  113. recorddef:
  114. begin
  115. getimplicitobjtemp(list,def,temptype,ref);
  116. result:=true;
  117. end;
  118. setdef:
  119. begin
  120. if tsetdef(def).elementdef.typ=enumdef then
  121. begin
  122. { load enum class type }
  123. list.concat(taicpu.op_sym(a_ldc,current_asmdata.RefAsmSymbol(tenumdef(tsetdef(def).elementdef).getbasedef.classdef.jvm_full_typename(true))));
  124. thlcgjvm(hlcg).incstack(current_asmdata.CurrAsmList,1);
  125. { call tenumset.noneOf() class method }
  126. sym:=tsym(tobjectdef(java_juenumset).symtable.find('NONEOF'));
  127. if assigned(sym) and
  128. (sym.typ=procsym) then
  129. begin
  130. if tprocsym(sym).procdeflist.Count<>1 then
  131. internalerror(2011062801);
  132. pd:=tprocdef(tprocsym(sym).procdeflist[0]);
  133. end;
  134. hlcg.a_call_name(list,pd,pd.mangledname,false);
  135. { static calls method replaces parameter with set instance
  136. -> no change in stack height }
  137. end
  138. else
  139. begin
  140. list.concat(taicpu.op_sym(a_new,current_asmdata.RefAsmSymbol(java_jubitset.jvm_full_typename(true))));
  141. { the constructor doesn't return anything, so put a duplicate of the
  142. self pointer on the evaluation stack for use as function result
  143. after the constructor has run }
  144. list.concat(taicpu.op_none(a_dup));
  145. thlcgjvm(hlcg).incstack(list,2);
  146. { call the constructor }
  147. sym:=tsym(java_jubitset.symtable.find('CREATE'));
  148. if assigned(sym) and
  149. (sym.typ=procsym) then
  150. begin
  151. pd:=tprocsym(sym).find_bytype_parameterless(potype_constructor);
  152. if not assigned(pd) then
  153. internalerror(2011062802);
  154. end
  155. else
  156. internalerror(2011062803);
  157. hlcg.a_call_name(list,pd,pd.mangledname,false);
  158. { duplicate self pointer is removed }
  159. thlcgjvm(hlcg).decstack(list,1);
  160. end;
  161. { store reference to instance }
  162. gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref);
  163. thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0);
  164. result:=true;
  165. end;
  166. procvardef:
  167. begin
  168. if not tprocvardef(def).is_addressonly then
  169. begin
  170. getimplicitobjtemp(list,tprocvardef(def).classdef,temptype,ref);
  171. result:=true;
  172. end;
  173. end;
  174. stringdef:
  175. begin
  176. if is_shortstring(def) then
  177. begin
  178. gettemp(list,java_jlobject.size,java_jlobject.alignment,temptype,ref);
  179. { add the maxlen parameter }
  180. thlcgjvm(hlcg).a_load_const_stack(list,u8inttype,tstringdef(def).len,R_INTREGISTER);
  181. { call the constructor }
  182. sym:=tsym(tobjectdef(java_shortstring).symtable.find('CREATEEMPTY'));
  183. if assigned(sym) and
  184. (sym.typ=procsym) then
  185. begin
  186. if tprocsym(sym).procdeflist.Count<>1 then
  187. internalerror(2011052404);
  188. pd:=tprocdef(tprocsym(sym).procdeflist[0]);
  189. end;
  190. hlcg.a_call_name(list,pd,pd.mangledname,false);
  191. { static calls method replaces parameter with string instance
  192. -> no change in stack height }
  193. { store reference to instance }
  194. thlcgjvm(hlcg).a_load_stack_ref(list,java_jlobject,ref,0);
  195. result:=true;
  196. end;
  197. end;
  198. end;
  199. end;
  200. function ttgjvm.alloctemp(list: TAsmList; size, alignment: longint; temptype: ttemptype; def: tdef): longint;
  201. begin
  202. { the JVM only supports 1 slot (= 4 bytes in FPC) and 2 slot (= 8 bytes in
  203. FPC) temps on the stack. double and int64 are 2 slots, the rest is one slot.
  204. There are no problems with reusing the same slot for a value of a different
  205. type. There are no alignment requirements either. }
  206. if size<4 then
  207. size:=4;
  208. if not(size in [4,8]) then
  209. internalerror(2010121401);
  210. { don't pass on "def", since we don't care if a slot is used again for a
  211. different type }
  212. result:=inherited alloctemp(list, size shr 2, 1, temptype, nil);
  213. end;
  214. procedure ttgjvm.setfirsttemp(l: longint);
  215. begin
  216. firsttemp:=l;
  217. lasttemp:=l;
  218. end;
  219. procedure ttgjvm.getlocal(list: TAsmList; size: longint; alignment: shortint; def: tdef; var ref: treference);
  220. begin
  221. if not getifspecialtemp(list,def,size,tt_persistent,ref) then
  222. inherited;
  223. end;
  224. procedure ttgjvm.gethltemp(list: TAsmList; def: tdef; forcesize: aint; temptype: ttemptype; out ref: treference);
  225. begin
  226. if not getifspecialtemp(list,def,forcesize,temptype,ref) then
  227. inherited;
  228. end;
  229. procedure ttgjvm.gethltemptyped(list: TAsmList; def: tdef; temptype: ttemptype; out ref: treference);
  230. begin
  231. gethltemp(list,def,def.size,temptype,ref);
  232. end;
  233. begin
  234. tgobjclass:=ttgjvm;
  235. end.