jvmdef.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  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. { same as above, but throws an internal error on failure }
  29. function jvmencodetype(def: tdef): string;
  30. { Check whether a type can be used in a JVM methom signature or field
  31. declaration. }
  32. function jvmchecktype(def: tdef; out founderror: tdef): boolean;
  33. { incremental version of jvmtryencodetype() }
  34. function jvmaddencodedtype(def: tdef; bpacked: boolean; var encodedstr: string; out founderror: tdef): boolean;
  35. { add type prefix (package name) to a type }
  36. procedure jvmaddtypeownerprefix(owner: tsymtable; var name: string);
  37. { generate internal static field name based on regular field name }
  38. function jvminternalstaticfieldname(const fieldname: string): string;
  39. { returns type string for a single-dimensional array (different from normal
  40. typestring in case of a primitive type) }
  41. function jvmarrtype(def: tdef; out primitivetype: boolean): string;
  42. function jvmarrtype_setlength(def: tdef): char;
  43. { returns whether a def is emulated using an implicit pointer type on the
  44. JVM target (e.g., records, regular arrays, ...) }
  45. function jvmimplicitpointertype(def: tdef): boolean;
  46. implementation
  47. uses
  48. globtype,
  49. cutils,cclasses,
  50. verbose,systems,
  51. fmodule,
  52. symtable,symconst,symsym,symdef,
  53. defutil,paramgr;
  54. {******************************************************************
  55. Type encoding
  56. *******************************************************************}
  57. function jvmaddencodedtype(def: tdef; bpacked: boolean; var encodedstr: string; out founderror: tdef): boolean;
  58. var
  59. c: char;
  60. begin
  61. result:=true;
  62. case def.typ of
  63. stringdef :
  64. begin
  65. case tstringdef(def).stringtype of
  66. { translated into Java.Lang.String }
  67. st_widestring:
  68. encodedstr:=encodedstr+'Ljava/lang/String;';
  69. else
  70. { May be handled via wrapping later }
  71. result:=false;
  72. end;
  73. end;
  74. enumdef,
  75. orddef :
  76. begin
  77. { for procedure "results" }
  78. if is_void(def) then
  79. c:='V'
  80. { only Pascal-style booleans conform to Java's definition of
  81. Boolean }
  82. else if is_pasbool(def) and
  83. (def.size=1) then
  84. c:='Z'
  85. else if is_widechar(def) then
  86. c:='C'
  87. else
  88. begin
  89. case def.size of
  90. 1:
  91. c:='B';
  92. 2:
  93. c:='S';
  94. 4:
  95. c:='I';
  96. 8:
  97. c:='J';
  98. else
  99. internalerror(2010121905);
  100. end;
  101. end;
  102. encodedstr:=encodedstr+c;
  103. end;
  104. pointerdef :
  105. begin
  106. { some may be handled via wrapping later }
  107. result:=false;
  108. end;
  109. floatdef :
  110. begin
  111. case tfloatdef(def).floattype of
  112. s32real:
  113. c:='F';
  114. s64real:
  115. c:='D';
  116. else
  117. result:=false;
  118. end;
  119. encodedstr:=encodedstr+c;
  120. end;
  121. filedef :
  122. result:=false;
  123. recorddef :
  124. begin
  125. { will be hanlded via wrapping later, although wrapping may
  126. happen at higher level }
  127. result:=false;
  128. end;
  129. variantdef :
  130. begin
  131. { will be hanlded via wrapping later, although wrapping may
  132. happen at higher level }
  133. result:=false;
  134. end;
  135. classrefdef :
  136. begin
  137. { may be handled via wrapping later }
  138. result:=false;
  139. end;
  140. setdef :
  141. begin
  142. if is_smallset(def) then
  143. encodedstr:=encodedstr+'I'
  144. else
  145. { will be hanlded via wrapping later, although wrapping may
  146. happen at higher level }
  147. result:=false;
  148. end;
  149. formaldef :
  150. begin
  151. { not supported (may be changed into "java.lang.Object" later) }
  152. result:=false;
  153. end;
  154. arraydef :
  155. begin
  156. if is_array_of_const(def) or
  157. is_packed_array(def) then
  158. result:=false
  159. else
  160. begin
  161. encodedstr:=encodedstr+'[';
  162. if not jvmaddencodedtype(tarraydef(def).elementdef,false,encodedstr,founderror) then
  163. begin
  164. result:=false;
  165. { report the exact (nested) error defintion }
  166. exit;
  167. end;
  168. end;
  169. end;
  170. procvardef :
  171. begin
  172. { will be hanlded via wrapping later, although wrapping may
  173. happen at higher level }
  174. result:=false;
  175. end;
  176. objectdef :
  177. case tobjectdef(def).objecttype of
  178. odt_javaclass,
  179. odt_interfacejava:
  180. encodedstr:=encodedstr+'L'+tobjectdef(def).jvm_full_typename(true)+';'
  181. else
  182. result:=false;
  183. end;
  184. undefineddef,
  185. errordef :
  186. result:=false;
  187. procdef :
  188. { must be done via jvmencodemethod() }
  189. internalerror(2010121903);
  190. else
  191. internalerror(2010121904);
  192. end;
  193. if not result then
  194. founderror:=def;
  195. end;
  196. function jvmtryencodetype(def: tdef; out encodedtype: string; out founderror: tdef): boolean;
  197. begin
  198. encodedtype:='';
  199. result:=jvmaddencodedtype(def,false,encodedtype,founderror);
  200. end;
  201. procedure jvmaddtypeownerprefix(owner: tsymtable; var name: string);
  202. var
  203. owningunit: tsymtable;
  204. tmpresult: string;
  205. begin
  206. { see tprocdef.jvmmangledbasename for description of the format }
  207. case owner.symtabletype of
  208. globalsymtable,
  209. staticsymtable,
  210. localsymtable:
  211. begin
  212. owningunit:=owner;
  213. while (owningunit.symtabletype in [localsymtable,objectsymtable,recordsymtable]) do
  214. owningunit:=owningunit.defowner.owner;
  215. tmpresult:=find_module_from_symtable(owningunit).realmodulename^+'/';
  216. end;
  217. objectsymtable:
  218. case tobjectdef(owner.defowner).objecttype of
  219. odt_javaclass,
  220. odt_interfacejava:
  221. begin
  222. tmpresult:=tobjectdef(owner.defowner).jvm_full_typename(true)+'/'
  223. end
  224. else
  225. internalerror(2010122606);
  226. end
  227. else
  228. internalerror(2010122605);
  229. end;
  230. name:=tmpresult+name;
  231. end;
  232. function jvminternalstaticfieldname(const fieldname: string): string;
  233. begin
  234. result:='$_static_'+fieldname;
  235. end;
  236. function jvmarrtype(def: tdef; out primitivetype: boolean): string;
  237. var
  238. errdef: tdef;
  239. begin
  240. if not jvmtryencodetype(def,result,errdef) then
  241. internalerror(2011012205);
  242. primitivetype:=false;
  243. if length(result)=1 then
  244. begin
  245. case result[1] of
  246. 'Z': result:='boolean';
  247. 'C': result:='char';
  248. 'B': result:='byte';
  249. 'S': result:='short';
  250. 'I': result:='int';
  251. 'J': result:='long';
  252. 'F': result:='float';
  253. 'D': result:='double';
  254. else
  255. internalerror(2011012206);
  256. end;
  257. primitivetype:=true;
  258. end
  259. else if (result[1]='L') then
  260. begin
  261. { in case of a class reference, strip the leading 'L' and the
  262. trailing ';' }
  263. setlength(result,length(result)-1);
  264. delete(result,1,1);
  265. end;
  266. { for arrays, use the actual reference type }
  267. end;
  268. function jvmarrtype_setlength(def: tdef): char;
  269. var
  270. errdef: tdef;
  271. res: string;
  272. begin
  273. if not jvmtryencodetype(def,res,errdef) then
  274. internalerror(2011012209);
  275. if length(res)=1 then
  276. result:=res[1]
  277. else
  278. result:='A';
  279. end;
  280. function jvmimplicitpointertype(def: tdef): boolean;
  281. begin
  282. case def.typ of
  283. arraydef:
  284. result:=(tarraydef(def).highrange>=tarraydef(def).lowrange) or
  285. is_open_array(def) or
  286. is_array_of_const(def) or
  287. is_array_constructor(def);
  288. recorddef:
  289. result:=true;
  290. objectdef:
  291. result:=is_object(def);
  292. setdef:
  293. result:=not is_smallset(def);
  294. stringdef :
  295. result:=tstringdef(def).stringtype in [st_shortstring,st_longstring];
  296. else
  297. result:=false;
  298. end;
  299. end;
  300. {******************************************************************
  301. jvm type validity checking
  302. *******************************************************************}
  303. function jvmencodetype(def: tdef): string;
  304. var
  305. errordef: tdef;
  306. begin
  307. if not jvmtryencodetype(def,result,errordef) then
  308. internalerror(2011012305);
  309. end;
  310. function jvmchecktype(def: tdef; out founderror: tdef): boolean;
  311. var
  312. encodedtype: string;
  313. begin
  314. { don't duplicate the code like in objcdef, since the resulting strings
  315. are much shorter here so it's not worth it }
  316. result:=jvmtryencodetype(def,encodedtype,founderror);
  317. end;
  318. end.