symcpu.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. {
  2. Copyright (c) 2014 by Florian Klaempfl
  3. Symbol table overrides for JVM
  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 symcpu;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,
  22. aasmdata,
  23. symtype,
  24. symdef,symsym;
  25. type
  26. { defs }
  27. tcpufiledef = class(tfiledef)
  28. end;
  29. tcpuvariantdef = class(tvariantdef)
  30. end;
  31. tcpuformaldef = class(tformaldef)
  32. end;
  33. tcpuforwarddef = class(tforwarddef)
  34. end;
  35. tcpuundefineddef = class(tundefineddef)
  36. end;
  37. tcpuerrordef = class(terrordef)
  38. end;
  39. tcpupointerdef = class(tpointerdef)
  40. end;
  41. tcpurecorddef = class(trecorddef)
  42. end;
  43. tcpuimplementedinterface = class(timplementedinterface)
  44. end;
  45. tcpuobjectdef = class(tobjectdef)
  46. end;
  47. tcpuclassrefdef = class(tclassrefdef)
  48. end;
  49. tcpuarraydef = class(tarraydef)
  50. end;
  51. tcpuorddef = class(torddef)
  52. end;
  53. tcpufloatdef = class(tfloatdef)
  54. end;
  55. tcpuprocvardef = class(tprocvardef)
  56. protected
  57. procedure ppuwrite_platform(ppufile: tcompilerppufile); override;
  58. procedure ppuload_platform(ppufile: tcompilerppufile); override;
  59. public
  60. { class representing this procvar on the Java side }
  61. classdef : tobjectdef;
  62. classdefderef : tderef;
  63. procedure buildderef;override;
  64. procedure deref;override;
  65. function getcopy: tstoreddef; override;
  66. end;
  67. tcpuprocdef = class(tprocdef)
  68. { generated assembler code; used by JVM backend so it can afterwards
  69. easily write out all methods grouped per class }
  70. exprasmlist : TAsmList;
  71. function jvmmangledbasename(signature: boolean): TSymStr;
  72. function mangledname: TSymStr; override;
  73. destructor destroy; override;
  74. end;
  75. tcpustringdef = class(tstringdef)
  76. end;
  77. tcpuenumdef = class(tenumdef)
  78. end;
  79. tcpusetdef = class(tsetdef)
  80. end;
  81. { syms }
  82. tcpulabelsym = class(tlabelsym)
  83. end;
  84. tcpuunitsym = class(tunitsym)
  85. end;
  86. tcpunamespacesym = class(tnamespacesym)
  87. end;
  88. tcpuprocsym = class(tprocsym)
  89. end;
  90. tcpuypesym = class(ttypesym)
  91. end;
  92. tcpufieldvarsym = class(tfieldvarsym)
  93. procedure set_externalname(const s: string); override;
  94. function mangledname: TSymStr; override;
  95. end;
  96. tcpulocalvarsym = class(tlocalvarsym)
  97. end;
  98. tcpuparavarsym = class(tparavarsym)
  99. end;
  100. tcpustaticvarsym = class(tstaticvarsym)
  101. procedure set_mangledname(const s: TSymStr); override;
  102. function mangledname: TSymStr; override;
  103. end;
  104. tcpuabsolutevarsym = class(tabsolutevarsym)
  105. end;
  106. tcpupropertysym = class(tpropertysym)
  107. end;
  108. tcpuconstsym = class(tconstsym)
  109. end;
  110. tcpuenumsym = class(tenumsym)
  111. end;
  112. tcpusyssym = class(tsyssym)
  113. end;
  114. implementation
  115. uses
  116. verbose,cutils,
  117. symconst,symbase,jvmdef,
  118. paramgr;
  119. {****************************************************************************
  120. tcpuprocdef
  121. ****************************************************************************}
  122. function tcpuprocdef.jvmmangledbasename(signature: boolean): TSymStr;
  123. var
  124. vs: tparavarsym;
  125. i: longint;
  126. founderror: tdef;
  127. tmpresult: TSymStr;
  128. container: tsymtable;
  129. begin
  130. { format:
  131. * method definition (in Jasmin):
  132. (private|protected|public) [static] method(parametertypes)returntype
  133. * method invocation
  134. package/class/method(parametertypes)returntype
  135. -> store common part: method(parametertypes)returntype and
  136. adorn as required when using it.
  137. }
  138. if not signature then
  139. begin
  140. { method name }
  141. { special names for constructors and class constructors }
  142. if proctypeoption=potype_constructor then
  143. tmpresult:='<init>'
  144. else if proctypeoption in [potype_class_constructor,potype_unitinit] then
  145. tmpresult:='<clinit>'
  146. else if po_has_importname in procoptions then
  147. begin
  148. if assigned(import_name) then
  149. tmpresult:=import_name^
  150. else
  151. internalerror(2010122608);
  152. end
  153. else
  154. begin
  155. tmpresult:=procsym.realname;
  156. if tmpresult[1]='$' then
  157. tmpresult:=copy(tmpresult,2,length(tmpresult)-1);
  158. { nested functions }
  159. container:=owner;
  160. while container.symtabletype=localsymtable do
  161. begin
  162. tmpresult:='$'+tprocdef(owner.defowner).procsym.realname+'$'+tostr(tprocdef(owner.defowner).procsym.symid)+'$'+tmpresult;
  163. container:=container.defowner.owner;
  164. end;
  165. end;
  166. end
  167. else
  168. tmpresult:='';
  169. { parameter types }
  170. tmpresult:=tmpresult+'(';
  171. { not the case for the main program (not required for defaultmangledname
  172. because setmangledname() is called for the main program; in case of
  173. the JVM, this only sets the importname, however) }
  174. if assigned(paras) then
  175. begin
  176. init_paraloc_info(callerside);
  177. for i:=0 to paras.count-1 do
  178. begin
  179. vs:=tparavarsym(paras[i]);
  180. { function result is not part of the mangled name }
  181. if vo_is_funcret in vs.varoptions then
  182. continue;
  183. { self pointer neither, except for class methods (the JVM only
  184. supports static class methods natively, so the self pointer
  185. here is a regular parameter as far as the JVM is concerned }
  186. if not(po_classmethod in procoptions) and
  187. (vo_is_self in vs.varoptions) then
  188. continue;
  189. { passing by reference is emulated by passing an array of one
  190. element containing the value; for types that aren't pointers
  191. in regular Pascal, simply passing the underlying pointer type
  192. does achieve regular call-by-reference semantics though;
  193. formaldefs always have to be passed like that because their
  194. contents can be replaced }
  195. if paramanager.push_copyout_param(vs.varspez,vs.vardef,proccalloption) then
  196. tmpresult:=tmpresult+'[';
  197. { Add the parameter type. }
  198. if not jvmaddencodedtype(vs.vardef,false,tmpresult,signature,founderror) then
  199. { an internalerror here is also triggered in case of errors in the source code }
  200. tmpresult:='<error>';
  201. end;
  202. end;
  203. tmpresult:=tmpresult+')';
  204. { And the type of the function result (void in case of a procedure and
  205. constructor). }
  206. if (proctypeoption in [potype_constructor,potype_class_constructor]) then
  207. jvmaddencodedtype(voidtype,false,tmpresult,signature,founderror)
  208. else if not jvmaddencodedtype(returndef,false,tmpresult,signature,founderror) then
  209. { an internalerror here is also triggered in case of errors in the source code }
  210. tmpresult:='<error>';
  211. result:=tmpresult;
  212. end;
  213. function tcpuprocdef.mangledname: TSymStr;
  214. begin
  215. if _mangledname='' then
  216. begin
  217. result:=jvmmangledbasename(false);
  218. if (po_has_importdll in procoptions) then
  219. begin
  220. { import_dll comes from "external 'import_dll_name' name 'external_name'" }
  221. if assigned(import_dll) then
  222. result:=import_dll^+'/'+result
  223. else
  224. internalerror(2010122607);
  225. end
  226. else
  227. jvmaddtypeownerprefix(owner,mangledname);
  228. _mangledname:=result;
  229. end
  230. else
  231. result:=_mangledname;
  232. end;
  233. destructor tcpuprocdef.destroy;
  234. begin
  235. exprasmlist.free;
  236. inherited destroy;
  237. end;
  238. {****************************************************************************
  239. tcpuprocvardef
  240. ****************************************************************************}
  241. procedure tcpuprocvardef.ppuwrite_platform(ppufile: tcompilerppufile);
  242. begin
  243. inherited;
  244. ppufile.putderef(classdefderef);
  245. end;
  246. procedure tcpuprocvardef.ppuload_platform(ppufile: tcompilerppufile);
  247. begin
  248. inherited;
  249. ppufile.getderef(classdefderef);
  250. end;
  251. procedure tcpuprocvardef.buildderef;
  252. begin
  253. inherited buildderef;
  254. classdefderef.build(classdef);
  255. end;
  256. procedure tcpuprocvardef.deref;
  257. begin
  258. inherited deref;
  259. classdef:=tobjectdef(classdefderef.resolve);
  260. end;
  261. function tcpuprocvardef.getcopy: tstoreddef;
  262. begin
  263. result:=inherited;
  264. tcpuprocvardef(result).classdef:=classdef;
  265. end;
  266. {****************************************************************************
  267. tcpustaticvarsym
  268. ****************************************************************************}
  269. procedure tcpustaticvarsym.set_mangledname(const s: TSymStr);
  270. begin
  271. inherited;
  272. _mangledname:=jvmmangledbasename(self,s,false);
  273. jvmaddtypeownerprefix(owner,_mangledname);
  274. end;
  275. function tcpustaticvarsym.mangledname: TSymStr;
  276. begin
  277. if _mangledname='' then
  278. begin
  279. if _mangledbasename='' then
  280. _mangledname:=jvmmangledbasename(self,false)
  281. else
  282. _mangledname:=jvmmangledbasename(self,_mangledbasename,false);
  283. jvmaddtypeownerprefix(owner,_mangledname);
  284. end;
  285. result:=_mangledname;
  286. end;
  287. {****************************************************************************
  288. tcpufieldvarsym
  289. ****************************************************************************}
  290. procedure tcpufieldvarsym.set_externalname(const s: string);
  291. begin
  292. { make sure it is recalculated }
  293. cachedmangledname:='';
  294. if is_java_class_or_interface(tdef(owner.defowner)) then
  295. begin
  296. externalname:=stringdup(s);
  297. include(varoptions,vo_has_mangledname);
  298. end
  299. else
  300. internalerror(2011031201);
  301. end;
  302. function tcpufieldvarsym.mangledname: TSymStr;
  303. begin
  304. if is_java_class_or_interface(tdef(owner.defowner)) or
  305. (tdef(owner.defowner).typ=recorddef) then
  306. begin
  307. if cachedmangledname<>'' then
  308. result:=cachedmangledname
  309. else
  310. begin
  311. result:=jvmmangledbasename(self,false);
  312. jvmaddtypeownerprefix(owner,result);
  313. cachedmangledname:=result;
  314. end;
  315. end
  316. else
  317. result:=inherited;
  318. end;
  319. begin
  320. { used tdef classes }
  321. cfiledef:=tcpufiledef;
  322. cvariantdef:=tcpuvariantdef;
  323. cformaldef:=tcpuformaldef;
  324. cforwarddef:=tcpuforwarddef;
  325. cundefineddef:=tcpuundefineddef;
  326. cerrordef:=tcpuerrordef;
  327. cpointerdef:=tcpupointerdef;
  328. crecorddef:=tcpurecorddef;
  329. cimplementedinterface:=tcpuimplementedinterface;
  330. cobjectdef:=tcpuobjectdef;
  331. cclassrefdef:=tcpuclassrefdef;
  332. carraydef:=tcpuarraydef;
  333. corddef:=tcpuorddef;
  334. cfloatdef:=tcpufloatdef;
  335. cprocvardef:=tcpuprocvardef;
  336. cprocdef:=tcpuprocdef;
  337. cstringdef:=tcpustringdef;
  338. cenumdef:=tcpuenumdef;
  339. csetdef:=tcpusetdef;
  340. { used tsym classes }
  341. clabelsym:=tcpulabelsym;
  342. cunitsym:=tcpuunitsym;
  343. cnamespacesym:=tcpunamespacesym;
  344. cprocsym:=tcpuprocsym;
  345. ctypesym:=tcpuypesym;
  346. cfieldvarsym:=tcpufieldvarsym;
  347. clocalvarsym:=tcpulocalvarsym;
  348. cparavarsym:=tcpuparavarsym;
  349. cstaticvarsym:=tcpustaticvarsym;
  350. cabsolutevarsym:=tcpuabsolutevarsym;
  351. cpropertysym:=tcpupropertysym;
  352. cconstsym:=tcpuconstsym;
  353. cenumsym:=tcpuenumsym;
  354. csyssym:=tcpusyssym;
  355. end.