jvmdef.pas 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. {
  2. Copyright (c) 2010 by Jonas Maebe
  3. This unit implements some JVM type helper routines (minimal
  4. unit dependencies, usable in symdef).
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. {$i fpcdefs.inc}
  19. unit jvmdef;
  20. interface
  21. uses
  22. node,
  23. symbase,symtype;
  24. { Encode a type into the internal format used by the JVM (descriptor).
  25. Returns false if a type is not representable by the JVM,
  26. and in that case also the failing definition. }
  27. function jvmtryencodetype(def: tdef; out encodedtype: string; out founderror: tdef): boolean;
  28. { Check whether a type can be used in a JVM methom signature or field
  29. declaration. }
  30. function jvmchecktype(def: tdef; out founderror: tdef): boolean;
  31. { incremental version of jvmtryencodetype() }
  32. function jvmaddencodedtype(def: tdef; bpacked: boolean; var encodedstr: string; out founderror: tdef): boolean;
  33. { add type prefix (package name) to a type }
  34. procedure jvmaddtypeownerprefix(owner: tsymtable; var name: string);
  35. { generate internal static field name based on regular field name }
  36. function jvminternalstaticfieldname(const fieldname: string): string;
  37. implementation
  38. uses
  39. globtype,
  40. cutils,cclasses,
  41. verbose,systems,
  42. fmodule,
  43. symtable,symconst,symsym,symdef,
  44. defutil,paramgr;
  45. {******************************************************************
  46. Type encoding
  47. *******************************************************************}
  48. function jvmaddencodedtype(def: tdef; bpacked: boolean; var encodedstr: string; out founderror: tdef): boolean;
  49. var
  50. c: char;
  51. begin
  52. result:=true;
  53. case def.typ of
  54. stringdef :
  55. begin
  56. case tstringdef(def).stringtype of
  57. { translated into Java.Lang.String }
  58. st_widestring:
  59. encodedstr:=encodedstr+'Ljava/lang/String;';
  60. else
  61. { May be handled via wrapping later }
  62. result:=false;
  63. end;
  64. end;
  65. enumdef,
  66. orddef :
  67. begin
  68. { for procedure "results" }
  69. if is_void(def) then
  70. c:='V'
  71. { only Pascal-style booleans conform to Java's definition of
  72. Boolean }
  73. else if is_pasbool(def) and
  74. (def.size=1) then
  75. c:='Z'
  76. else if is_widechar(def) then
  77. c:='C'
  78. else
  79. begin
  80. case def.size of
  81. 1:
  82. c:='B';
  83. 2:
  84. c:='S';
  85. 4:
  86. c:='I';
  87. 8:
  88. c:='J';
  89. else
  90. internalerror(2010121905);
  91. end;
  92. end;
  93. encodedstr:=encodedstr+c;
  94. end;
  95. pointerdef :
  96. begin
  97. { some may be handled via wrapping later }
  98. result:=false;
  99. end;
  100. floatdef :
  101. begin
  102. case tfloatdef(def).floattype of
  103. s32real:
  104. c:='F';
  105. s64real:
  106. c:='D';
  107. else
  108. result:=false;
  109. end;
  110. encodedstr:=encodedstr+c;
  111. end;
  112. filedef :
  113. result:=false;
  114. recorddef :
  115. begin
  116. { will be hanlded via wrapping later, although wrapping may
  117. happen at higher level }
  118. result:=false;
  119. end;
  120. variantdef :
  121. begin
  122. { will be hanlded via wrapping later, although wrapping may
  123. happen at higher level }
  124. result:=false;
  125. end;
  126. classrefdef :
  127. begin
  128. { may be handled via wrapping later }
  129. result:=false;
  130. end;
  131. setdef :
  132. begin
  133. { will be hanlded via wrapping later, although wrapping may
  134. happen at higher level }
  135. result:=false;
  136. end;
  137. formaldef :
  138. begin
  139. { not supported (may be changed into "java.lang.Object" later) }
  140. result:=false;
  141. end;
  142. arraydef :
  143. begin
  144. if is_array_of_const(def) or
  145. is_open_array(def) or
  146. is_packed_array(def) then
  147. result:=false
  148. else
  149. begin
  150. encodedstr:=encodedstr+'[';
  151. if not jvmaddencodedtype(tarraydef(def).elementdef,false,encodedstr,founderror) then
  152. begin
  153. result:=false;
  154. { report the exact (nested) error defintion }
  155. exit;
  156. end;
  157. end;
  158. end;
  159. procvardef :
  160. begin
  161. { will be hanlded via wrapping later, although wrapping may
  162. happen at higher level }
  163. result:=false;
  164. end;
  165. objectdef :
  166. case tobjectdef(def).objecttype of
  167. odt_javaclass,
  168. odt_interfacejava:
  169. encodedstr:=encodedstr+'L'+tobjectdef(def).jvm_full_typename+';'
  170. else
  171. result:=false;
  172. end;
  173. undefineddef,
  174. errordef :
  175. result:=false;
  176. procdef :
  177. { must be done via jvmencodemethod() }
  178. internalerror(2010121903);
  179. else
  180. internalerror(2010121904);
  181. end;
  182. if not result then
  183. founderror:=def;
  184. end;
  185. function jvmtryencodetype(def: tdef; out encodedtype: string; out founderror: tdef): boolean;
  186. begin
  187. encodedtype:='';
  188. result:=jvmaddencodedtype(def,false,encodedtype,founderror);
  189. end;
  190. procedure jvmaddtypeownerprefix(owner: tsymtable; var name: string);
  191. var
  192. owningunit: tsymtable;
  193. tmpresult: string;
  194. begin
  195. { see tprocdef.jvmmangledbasename for description of the format }
  196. case owner.symtabletype of
  197. globalsymtable,
  198. staticsymtable,
  199. localsymtable:
  200. begin
  201. owningunit:=owner;
  202. while (owningunit.symtabletype in [localsymtable,objectsymtable,recordsymtable]) do
  203. owningunit:=owningunit.defowner.owner;
  204. tmpresult:=find_module_from_symtable(owningunit).realmodulename^+'/';
  205. end;
  206. objectsymtable:
  207. case tobjectdef(owner.defowner).objecttype of
  208. odt_javaclass,
  209. odt_interfacejava:
  210. begin
  211. tmpresult:=tobjectdef(owner.defowner).jvm_full_typename+'/'
  212. end
  213. else
  214. internalerror(2010122606);
  215. end
  216. else
  217. internalerror(2010122605);
  218. end;
  219. name:=tmpresult+name;
  220. end;
  221. function jvminternalstaticfieldname(const fieldname: string): string;
  222. begin
  223. result:='$_static_'+fieldname;
  224. end;
  225. {******************************************************************
  226. jvm type validity checking
  227. *******************************************************************}
  228. function jvmchecktype(def: tdef; out founderror: tdef): boolean;
  229. var
  230. encodedtype: string;
  231. begin
  232. { don't duplicate the code like in objcdef, since the resulting strings
  233. are much shorter here so it's not worth it }
  234. result:=jvmtryencodetype(def,encodedtype,founderror);
  235. end;
  236. end.