njvmutil.pas 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. {
  2. Copyright (c) 20011 by Jonas Maebe
  3. JVM version of some node tree helper routines
  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 njvmutil;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,
  22. ngenutil,
  23. symtype,symconst,symsym;
  24. type
  25. tjvmnodeutils = class(tnodeutils)
  26. class function initialize_data_node(p:tnode):tnode; override;
  27. class function finalize_data_node(p:tnode):tnode; override;
  28. class function force_init: boolean; override;
  29. class procedure insertbssdata(sym: tstaticvarsym); override;
  30. class function create_main_procdef(const name: string; potype: tproctypeoption; ps: tprocsym): tdef; override;
  31. class procedure InsertInitFinalTable; override;
  32. class procedure InsertThreadvarTablesTable; override;
  33. class procedure InsertThreadvars; override;
  34. class procedure InsertWideInitsTablesTable; override;
  35. class procedure InsertWideInits; override;
  36. class procedure InsertResourceTablesTable; override;
  37. class procedure InsertResourceInfo(ResourcesUsed : boolean); override;
  38. class procedure InsertMemorySizes; override;
  39. strict protected
  40. class procedure add_main_procdef_paras(pd: tdef); override;
  41. end;
  42. implementation
  43. uses
  44. verbose,cutils,globals,constexp,fmodule,
  45. aasmdata,aasmtai,cpubase,aasmcpu,
  46. symdef,symbase,symtable,defutil,jvmdef,
  47. nbas,ncnv,ncon,ninl,ncal,
  48. ppu,
  49. pass_1;
  50. class function tjvmnodeutils.initialize_data_node(p:tnode):tnode;
  51. begin
  52. if not assigned(p.resultdef) then
  53. typecheckpass(p);
  54. if ((p.resultdef.typ=stringdef) and
  55. not is_shortstring(p.resultdef) and
  56. not is_longstring(p.resultdef)) or
  57. is_dynamic_array(p.resultdef) then
  58. begin
  59. { Always initialise with empty string/array rather than nil. Java
  60. makes a distinction between an empty string/array and a null
  61. string/array, but we don't. We therefore have to pick which one we
  62. use to represent empty strings/arrays. I've chosen empty rather than
  63. null structures, because otherwise it becomes impossible to return
  64. an empty string to Java code (it would return null).
  65. On the consumer side, we do interpret both null and empty as the same
  66. thing, so Java code can pass in null strings/arrays and we'll
  67. interpret them correctly.
  68. }
  69. result:=cinlinenode.create(in_setlength_x,false,
  70. ccallparanode.create(genintconstnode(0),
  71. ccallparanode.create(p,nil)));
  72. end
  73. else
  74. begin
  75. p.free;
  76. { records/arrays/... are automatically initialised }
  77. result:=cnothingnode.create;
  78. end;
  79. end;
  80. class function tjvmnodeutils.finalize_data_node(p:tnode):tnode;
  81. begin
  82. // do nothing
  83. p.free;
  84. result:=cnothingnode.create;
  85. end;
  86. class function tjvmnodeutils.force_init: boolean;
  87. begin
  88. { we need an initialisation in case the al_globals list is not empty
  89. (that's where the initialisation for global records etc is added) }
  90. { problem: some bss symbols are only registered while processing the main
  91. program (e.g. constant sets) -> cannot predict whether or not we'll
  92. need it in advance }
  93. result:=true;
  94. end;
  95. class procedure tjvmnodeutils.insertbssdata(sym: tstaticvarsym);
  96. begin
  97. { handled while generating the unit/program init code, or class
  98. constructor; add something to al_globals to indicate that we need to
  99. insert an init section though }
  100. if current_asmdata.asmlists[al_globals].empty and
  101. jvmimplicitpointertype(sym.vardef) then
  102. current_asmdata.asmlists[al_globals].concat(cai_align.Create(1));
  103. end;
  104. class function tjvmnodeutils.create_main_procdef(const name: string; potype: tproctypeoption; ps: tprocsym): tdef;
  105. begin
  106. if (potype=potype_proginit) then
  107. begin
  108. result:=inherited create_main_procdef('main', potype, ps);
  109. include(tprocdef(result).procoptions,po_global);
  110. tprocdef(result).visibility:=vis_public;
  111. end
  112. else
  113. result:=inherited create_main_procdef(name, potype, ps);
  114. end;
  115. class procedure tjvmnodeutils.InsertInitFinalTable;
  116. var
  117. hp : tused_unit;
  118. unitinits : TAsmList;
  119. unitclassname: string;
  120. mainpsym: tsym;
  121. mainpd: tprocdef;
  122. begin
  123. unitinits:=TAsmList.Create;
  124. hp:=tused_unit(usedunits.first);
  125. while assigned(hp) do
  126. begin
  127. { class constructors are automatically handled by the JVM }
  128. { call the unit init code and make it external }
  129. if (hp.u.flags and (uf_init or uf_finalize))<>0 then
  130. begin
  131. { trigger init code by referencing the class representing the
  132. unit; if necessary, it will register the fini code to run on
  133. exit}
  134. unitclassname:='';
  135. if assigned(hp.u.namespace) then
  136. begin
  137. unitclassname:=hp.u.namespace^+'/';
  138. replace(unitclassname,'.','/');
  139. end;
  140. unitclassname:=unitclassname+hp.u.realmodulename^;
  141. unitinits.concat(taicpu.op_sym(a_new,current_asmdata.RefAsmSymbol(unitclassname)));
  142. unitinits.concat(taicpu.op_none(a_pop));
  143. end;
  144. hp:=tused_unit(hp.next);
  145. end;
  146. { insert in main program routine }
  147. mainpsym:=tsym(current_module.localsymtable.find(mainaliasname));
  148. if not assigned(mainpsym) or
  149. (mainpsym.typ<>procsym) then
  150. internalerror(2011041901);
  151. mainpd:=tprocsym(mainpsym).find_procdef_bytype(potype_proginit);
  152. if not assigned(mainpd) then
  153. internalerror(2011041902);
  154. mainpd.exprasmlist.insertList(unitinits);
  155. unitinits.free;
  156. end;
  157. class procedure tjvmnodeutils.InsertThreadvarTablesTable;
  158. begin
  159. { not yet supported }
  160. end;
  161. class procedure tjvmnodeutils.InsertThreadvars;
  162. begin
  163. { not yet supported }
  164. end;
  165. class procedure tjvmnodeutils.InsertWideInitsTablesTable;
  166. begin
  167. { not required }
  168. end;
  169. class procedure tjvmnodeutils.InsertWideInits;
  170. begin
  171. { not required }
  172. end;
  173. class procedure tjvmnodeutils.InsertResourceTablesTable;
  174. begin
  175. { not supported }
  176. end;
  177. class procedure tjvmnodeutils.InsertResourceInfo(ResourcesUsed: boolean);
  178. begin
  179. { not supported }
  180. end;
  181. class procedure tjvmnodeutils.InsertMemorySizes;
  182. begin
  183. { not required }
  184. end;
  185. class procedure tjvmnodeutils.add_main_procdef_paras(pd: tdef);
  186. var
  187. pvs: tparavarsym;
  188. begin
  189. if (tprocdef(pd).proctypeoption=potype_proginit) then
  190. begin
  191. { add the args parameter }
  192. pvs:=tparavarsym.create('$args',1,vs_const,search_system_type('TJSTRINGARRAY').typedef,[]);
  193. tprocdef(pd).parast.insert(pvs);
  194. tprocdef(pd).calcparas;
  195. end;
  196. end;
  197. begin
  198. cnodeutils:=tjvmnodeutils;
  199. end.