njvmtcon.pas 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. {
  2. Copyright (c) 2011 by Jonas Maebe
  3. Generates nodes for typed constant declarations
  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 njvmtcon;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. node,
  23. symtype,symdef,
  24. ngtcon;
  25. type
  26. tarrstringdata = record
  27. arrstring: ansistring;
  28. arrdatastart, arrdatalen: asizeint;
  29. arraybase: tnode;
  30. end;
  31. tjvmtypedconstbuilder = class(tnodetreetypedconstbuilder)
  32. private
  33. procedure tc_flush_arr_strconst(def: tdef);
  34. protected
  35. arrstringdata: tarrstringdata;
  36. parsingordarray: boolean;
  37. procedure parse_arraydef(def: tarraydef); override;
  38. procedure tc_emit_setdef(def: tsetdef; var node: tnode);override;
  39. procedure tc_emit_orddef(def: torddef; var node: tnode); override;
  40. end;
  41. implementation
  42. uses
  43. globals,widestr,verbose,constexp,
  44. defutil,
  45. nbas,ncal,ncon,njvmcon;
  46. procedure init_arrstringdata(out data: tarrstringdata);
  47. begin
  48. data.arrstring:='';
  49. data.arrdatastart:=0;
  50. data.arrdatalen:=0;
  51. data.arraybase:=nil;
  52. end;
  53. procedure tjvmtypedconstbuilder.tc_flush_arr_strconst(def: tdef);
  54. var
  55. wstr: pcompilerwidestring;
  56. wc: tcompilerwidechar;
  57. i: longint;
  58. procvariant: string[8];
  59. begin
  60. // convert ansistring to packed unicodestring
  61. initwidestring(wstr);
  62. for i:=1 to length(arrstringdata.arrstring) div 2 do
  63. begin
  64. wc:=tcompilerwidechar(ord(arrstringdata.arrstring[i*2-1]) shl 8 or
  65. ord(arrstringdata.arrstring[i*2]));
  66. concatwidestringchar(wstr,wc);
  67. end;
  68. if odd(length(arrstringdata.arrstring)) then
  69. concatwidestringchar(wstr,
  70. tcompilerwidechar(ord(arrstringdata.arrstring[length(arrstringdata.arrstring)]) shl 8));
  71. if is_signed(def) then
  72. case def.size of
  73. 1: procvariant:='shortint';
  74. 2: procvariant:='smallint';
  75. 4: procvariant:='longint';
  76. 8: procvariant:='int64';
  77. else
  78. internalerror(2011111301);
  79. end
  80. else
  81. case def.size of
  82. 1: procvariant:='byte';
  83. 2: procvariant:='word';
  84. 4: procvariant:='cardinal';
  85. 8: procvariant:='qword';
  86. else
  87. internalerror(2011111302);
  88. end;
  89. // (const s: unicodestring; var arr: array of shortint; startintdex, len: longint);
  90. addstatement(statmnt,ccallnode.createintern('fpc_tcon_'+procvariant+'_array_from_string',
  91. ccallparanode.create(genintconstnode(arrstringdata.arrdatalen),
  92. ccallparanode.create(genintconstnode(arrstringdata.arrdatastart),
  93. ccallparanode.create(arrstringdata.arraybase.getcopy,
  94. ccallparanode.create(cstringconstnode.createunistr(wstr),nil))))));
  95. inc(arrstringdata.arrdatastart,arrstringdata.arrdatalen);
  96. arrstringdata.arrstring:='';
  97. arrstringdata.arrdatalen:=0;
  98. donewidestring(wstr);
  99. end;
  100. procedure tjvmtypedconstbuilder.parse_arraydef(def: tarraydef);
  101. var
  102. old_arrstringdata: tarrstringdata;
  103. old_parsingordarray: boolean;
  104. begin
  105. if is_dynamic_array(def) or
  106. not is_integer(def.elementdef) or
  107. not(ts_compact_int_array_init in current_settings.targetswitches) then
  108. begin
  109. inherited;
  110. exit;
  111. end;
  112. old_arrstringdata:=arrstringdata;
  113. init_arrstringdata(arrstringdata);
  114. arrstringdata.arraybase:=basenode.getcopy;
  115. old_parsingordarray:=parsingordarray;
  116. parsingordarray:=true;
  117. inherited;
  118. if length(arrstringdata.arrstring)<>0 then
  119. tc_flush_arr_strconst(def.elementdef);
  120. arrstringdata.arraybase.free;
  121. parsingordarray:=old_parsingordarray;
  122. arrstringdata:=old_arrstringdata;
  123. end;
  124. procedure tjvmtypedconstbuilder.tc_emit_setdef(def: tsetdef; var node: tnode);
  125. begin
  126. { indicate that set constant nodes have to be transformed into
  127. constructors here }
  128. if node.nodetype=setconstn then
  129. tjvmsetconstnode(node).setconsttype:=sct_construct;
  130. inherited tc_emit_setdef(def,node);
  131. end;
  132. procedure tjvmtypedconstbuilder.tc_emit_orddef(def: torddef; var node: tnode);
  133. var
  134. elesize: longint;
  135. begin
  136. if not parsingordarray then
  137. begin
  138. inherited;
  139. exit;
  140. end;
  141. if node.nodetype<>ordconstn then
  142. internalerror(2011111101);
  143. elesize:=def.size;
  144. inc(arrstringdata.arrdatalen);
  145. case elesize of
  146. 1:
  147. arrstringdata.arrstring:=arrstringdata.arrstring+char(tordconstnode(node).value.svalue);
  148. 2:
  149. arrstringdata.arrstring:=arrstringdata.arrstring+char(tordconstnode(node).value.svalue shr 8)+char(tordconstnode(node).value.svalue and $ff);
  150. 4:
  151. arrstringdata.arrstring:=arrstringdata.arrstring+char((tordconstnode(node).value.svalue shr 24))+
  152. char((tordconstnode(node).value.svalue shr 16) and $ff)+
  153. char((tordconstnode(node).value.svalue shr 8) and $ff)+
  154. char(tordconstnode(node).value.svalue and $ff);
  155. 8:
  156. arrstringdata.arrstring:=arrstringdata.arrstring+char((tordconstnode(node).value.svalue shr 56))+
  157. char((tordconstnode(node).value.svalue shr 48) and $ff)+
  158. char((tordconstnode(node).value.svalue shr 40) and $ff)+
  159. char((tordconstnode(node).value.svalue shr 32) and $ff)+
  160. char((tordconstnode(node).value.svalue shr 24) and $ff)+
  161. char((tordconstnode(node).value.svalue shr 16) and $ff)+
  162. char((tordconstnode(node).value.svalue shr 8) and $ff)+
  163. char(tordconstnode(node).value.svalue and $ff);
  164. end;
  165. { we can't use the full 64kb, because inside the Java class file the
  166. string constant is actually encoded using UTF-8 and it's this UTF-8
  167. encoding that has to fit inside 64kb (and utf-8 encoding of random
  168. data can easily blow up its size by about a third) }
  169. if length(arrstringdata.arrstring)>40000 then
  170. tc_flush_arr_strconst(def);
  171. basenode.free;
  172. basenode:=nil;
  173. node.free;
  174. node:=nil;
  175. end;
  176. begin
  177. ctypedconstbuilder:=tjvmtypedconstbuilder;
  178. end.