jvmdef.pas 10 KB

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