njvmld.pas 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  1. {
  2. Copyright (c) 2011 by Jonas Maebe
  3. Generate JVM assembler for nodes that handle loads and assignments
  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 njvmld;
  18. {$I fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. symtype,
  23. cgutils,
  24. node, ncgld, ncgnstld;
  25. type
  26. tjvmloadnode = class(tcgnestloadnode)
  27. protected
  28. function is_copyout_addr_param_load: boolean;
  29. public
  30. function is_addr_param_load: boolean; override;
  31. procedure pass_generate_code; override;
  32. end;
  33. tjvmassignmentnode = class(tcgassignmentnode)
  34. function pass_1: tnode; override;
  35. end;
  36. tjvmarrayconstructornode = class(tcgarrayconstructornode)
  37. protected
  38. procedure makearrayref(var ref: treference; eledef: tdef); override;
  39. procedure advancearrayoffset(var ref: treference; elesize: asizeint); override;
  40. end;
  41. implementation
  42. uses
  43. verbose,
  44. aasmdata,
  45. nbas,nld,ncal,ncon,ninl,nmem,ncnv,
  46. symconst,symsym,symdef,symtable,defutil,jvmdef,
  47. paramgr,
  48. pass_1,
  49. cgbase,hlcgobj;
  50. { tjvmassignmentnode }
  51. function tjvmassignmentnode.pass_1: tnode;
  52. var
  53. block: tblocknode;
  54. tempn: ttempcreatenode;
  55. stat: tstatementnode;
  56. target: tnode;
  57. psym: tsym;
  58. begin
  59. { intercept writes to string elements, because Java strings are immutable
  60. -> detour via StringBuilder
  61. }
  62. target:=left.actualtargetnode;
  63. if (target.nodetype=vecn) and
  64. (is_wide_or_unicode_string(tvecnode(target).left.resultdef) or
  65. is_ansistring(tvecnode(target).left.resultdef)) then
  66. begin
  67. { prevent errors in case of an expression such as
  68. word(str[x]):=1234;
  69. }
  70. inserttypeconv_explicit(right,cwidechartype);
  71. result:=ccallnode.createintern('fpc_'+tstringdef(tvecnode(target).left.resultdef).stringtypname+'_setchar',
  72. ccallparanode.create(right,
  73. ccallparanode.create(tvecnode(target).right,
  74. ccallparanode.create(tvecnode(target).left.getcopy,nil))));
  75. result:=cassignmentnode.create(tvecnode(target).left,result);
  76. right:=nil;
  77. tvecnode(target).left:=nil;
  78. tvecnode(target).right:=nil;
  79. exit;
  80. end
  81. else if (target.nodetype=vecn) and
  82. is_shortstring(tvecnode(target).left.resultdef) then
  83. begin
  84. { prevent errors in case of an expression such as
  85. byte(str[x]):=12;
  86. }
  87. inserttypeconv_explicit(right,cchartype);
  88. { call ShortstringClass(@shortstring).setChar(index,char) }
  89. tvecnode(target).left:=caddrnode.create_internal(tvecnode(target).left);
  90. { avoid useless typecheck when casting to shortstringclass }
  91. include(tvecnode(target).left.flags,nf_typedaddr);
  92. inserttypeconv_explicit(tvecnode(target).left,java_shortstring);
  93. psym:=search_struct_member(tabstractrecorddef(java_shortstring),'SETCHAR');
  94. if not assigned(psym) or
  95. (psym.typ<>procsym) then
  96. internalerror(2011052408);
  97. result:=
  98. ccallnode.create(
  99. ccallparanode.create(right,
  100. ccallparanode.create(tvecnode(target).right,nil)),
  101. tprocsym(psym),psym.owner,tvecnode(target).left,[]);
  102. right:=nil;
  103. tvecnode(target).left:=nil;
  104. tvecnode(target).right:=nil;
  105. exit;
  106. end
  107. else if target.resultdef.typ=formaldef then
  108. begin
  109. if right.resultdef.typ in [orddef,floatdef] then
  110. right:=cinlinenode.create(in_box_x,false,right)
  111. else if jvmimplicitpointertype(right.resultdef) then
  112. begin
  113. { we have to assign the address of a deep copy of the type to the
  114. object in the formalpara -> create a temp, assign the value to
  115. the temp, then assign the address in the temp to the para }
  116. block:=internalstatements(stat);
  117. tempn:=ctempcreatenode.create_value(right.resultdef,right.resultdef.size,
  118. tt_persistent,false,right);
  119. addstatement(stat,tempn);
  120. right:=caddrnode.create(ctemprefnode.create(tempn));
  121. inserttypeconv_explicit(right,java_jlobject);
  122. addstatement(stat,ctempdeletenode.create_normal_temp(tempn));
  123. addstatement(stat,ctypeconvnode.create_explicit(
  124. caddrnode.create(ctemprefnode.create(tempn)),java_jlobject));
  125. right:=block;
  126. end;
  127. typecheckpass(right);
  128. result:=inherited;
  129. exit;
  130. end
  131. else
  132. result:=inherited;
  133. end;
  134. function tjvmloadnode.is_copyout_addr_param_load: boolean;
  135. begin
  136. result:=
  137. { passed via array of one element }
  138. ((symtable.symtabletype=parasymtable) and
  139. (symtableentry.typ=paravarsym) and
  140. paramanager.push_copyout_param(tparavarsym(symtableentry).varspez,resultdef,tprocdef(symtable.defowner).proccalloption));
  141. end;
  142. function tjvmloadnode.is_addr_param_load: boolean;
  143. begin
  144. result:=
  145. (inherited and
  146. not jvmimplicitpointertype(tparavarsym(symtableentry).vardef) and
  147. (tparavarsym(symtableentry).vardef.typ<>formaldef)) or
  148. is_copyout_addr_param_load;
  149. end;
  150. procedure tjvmloadnode.pass_generate_code;
  151. begin
  152. if is_copyout_addr_param_load then
  153. begin
  154. { in case of nested access, load address of field in nestedfpstruct }
  155. if assigned(left) then
  156. generate_nested_access(tabstractnormalvarsym(symtableentry));
  157. location_reset_ref(location,LOC_REFERENCE,def_cgsize(resultdef),4);
  158. location.reference.arrayreftype:=art_indexconst;
  159. location.reference.base:=hlcg.getaddressregister(current_asmdata.CurrAsmList,java_jlobject);
  160. location.reference.indexoffset:=0;
  161. { load the field from the nestedfpstruct, or the parameter location.
  162. In both cases, the result is an array of one element containing the
  163. parameter value }
  164. if assigned(left) then
  165. hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,java_jlobject,java_jlobject,left.location,location.reference.base)
  166. else
  167. hlcg.a_load_loc_reg(current_asmdata.CurrAsmList,java_jlobject,java_jlobject,tparavarsym(symtableentry).localloc,location.reference.base);
  168. end
  169. else if symtableentry.typ=procsym then
  170. { handled in tjvmcnvnode.first_proc_to_procvar }
  171. internalerror(2011072408)
  172. else
  173. inherited pass_generate_code;
  174. end;
  175. { tjvmarrayconstructornode }
  176. procedure tjvmarrayconstructornode.makearrayref(var ref: treference; eledef: tdef);
  177. var
  178. basereg: tregister;
  179. begin
  180. { arrays are implicitly dereferenced }
  181. basereg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,java_jlobject);
  182. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,java_jlobject,java_jlobject,ref,basereg);
  183. reference_reset_base(ref,basereg,0,1);
  184. ref.arrayreftype:=art_indexconst;
  185. ref.indexoffset:=0;
  186. end;
  187. procedure tjvmarrayconstructornode.advancearrayoffset(var ref: treference; elesize: asizeint);
  188. begin
  189. inc(ref.indexoffset);
  190. end;
  191. begin
  192. cloadnode:=tjvmloadnode;
  193. cassignmentnode:=tjvmassignmentnode;
  194. carrayconstructornode:=tjvmarrayconstructornode;
  195. end.