symcpu.pas 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946
  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. tcpufiledefclass = class of tcpufiledef;
  30. tcpuvariantdef = class(tvariantdef)
  31. end;
  32. tcpuvariantdefclass = class of tcpuvariantdef;
  33. tcpuformaldef = class(tformaldef)
  34. end;
  35. tcpuformaldefclass = class of tcpuformaldef;
  36. tcpuforwarddef = class(tforwarddef)
  37. end;
  38. tcpuforwarddefclass = class of tcpuforwarddef;
  39. tcpuundefineddef = class(tundefineddef)
  40. end;
  41. tcpuundefineddefclass = class of tcpuundefineddef;
  42. tcpuerrordef = class(terrordef)
  43. end;
  44. tcpuerrordefclass = class of tcpuerrordef;
  45. tcpupointerdef = class(tpointerdef)
  46. end;
  47. tcpupointerdefclass = class of tcpupointerdef;
  48. tcpurecorddef = class(trecorddef)
  49. end;
  50. tcpurecorddefclass = class of tcpurecorddef;
  51. tcpuimplementedinterface = class(timplementedinterface)
  52. end;
  53. tcpuimplementedinterfaceclass = class of tcpuimplementedinterface;
  54. tcpuobjectdef = class(tobjectdef)
  55. end;
  56. tcpuobjectdefclass = class of tcpuobjectdef;
  57. tcpuclassrefdef = class(tclassrefdef)
  58. end;
  59. tcpuclassrefdefclass = class of tcpuclassrefdef;
  60. tcpuarraydef = class(tarraydef)
  61. end;
  62. tcpuarraydefclass = class of tcpuarraydef;
  63. tcpuorddef = class(torddef)
  64. end;
  65. tcpuorddefclass = class of tcpuorddef;
  66. tcpufloatdef = class(tfloatdef)
  67. end;
  68. tcpufloatdefclass = class of tcpufloatdef;
  69. tcpuprocvardef = class(tprocvardef)
  70. protected
  71. procedure ppuwrite_platform(ppufile: tcompilerppufile); override;
  72. procedure ppuload_platform(ppufile: tcompilerppufile); override;
  73. public
  74. { class representing this procvar on the Java side }
  75. classdef : tobjectdef;
  76. classdefderef : tderef;
  77. procedure buildderef;override;
  78. procedure deref;override;
  79. function getcopy: tstoreddef; override;
  80. end;
  81. tcpuprocvardefclass = class of tcpuprocvardef;
  82. tcpuprocdef = class(tprocdef)
  83. { generated assembler code; used by JVM backend so it can afterwards
  84. easily write out all methods grouped per class }
  85. exprasmlist : TAsmList;
  86. function jvmmangledbasename(signature: boolean): TSymStr;
  87. function mangledname: TSymStr; override;
  88. destructor destroy; override;
  89. end;
  90. tcpuprocdefclass = class of tcpuprocdef;
  91. tcpustringdef = class(tstringdef)
  92. end;
  93. tcpustringdefclass = class of tcpustringdef;
  94. tcpuenumdef = class(tenumdef)
  95. protected
  96. procedure ppuload_platform(ppufile: tcompilerppufile); override;
  97. procedure ppuwrite_platform(ppufile: tcompilerppufile); override;
  98. public
  99. { class representing this enum on the Java side }
  100. classdef : tobjectdef;
  101. classdefderef : tderef;
  102. function getcopy: tstoreddef; override;
  103. procedure buildderef; override;
  104. procedure deref; override;
  105. end;
  106. tcpuenumdefclass = class of tcpuenumdef;
  107. tcpusetdef = class(tsetdef)
  108. end;
  109. tcpusetdefclass = class of tcpusetdef;
  110. { syms }
  111. tcpulabelsym = class(tlabelsym)
  112. end;
  113. tcpulabelsymclass = class of tcpulabelsym;
  114. tcpuunitsym = class(tunitsym)
  115. end;
  116. tcpuunitsymclass = class of tcpuunitsym;
  117. tcpunamespacesym = class(tnamespacesym)
  118. end;
  119. tcpunamespacesymclass = class of tcpunamespacesym;
  120. tcpuprocsym = class(tprocsym)
  121. procedure check_forward; override;
  122. end;
  123. tcpuprocsymclass = class of tcpuprocsym;
  124. tcputypesym = class(ttypesym)
  125. end;
  126. tcpuypesymclass = class of tcputypesym;
  127. tcpufieldvarsym = class(tfieldvarsym)
  128. procedure set_externalname(const s: string); override;
  129. function mangledname: TSymStr; override;
  130. end;
  131. tcpufieldvarsymclass = class of tcpufieldvarsym;
  132. tcpulocalvarsym = class(tlocalvarsym)
  133. end;
  134. tcpulocalvarsymclass = class of tcpulocalvarsym;
  135. tcpuparavarsym = class(tparavarsym)
  136. end;
  137. tcpuparavarsymclass = class of tcpuparavarsym;
  138. tcpustaticvarsym = class(tstaticvarsym)
  139. procedure set_mangledname(const s: TSymStr); override;
  140. function mangledname: TSymStr; override;
  141. end;
  142. tcpustaticvarsymclass = class of tcpustaticvarsym;
  143. tcpuabsolutevarsym = class(tabsolutevarsym)
  144. end;
  145. tcpuabsolutevarsymclass = class of tcpuabsolutevarsym;
  146. tcpupropertysym = class(tpropertysym)
  147. protected
  148. { when a private/protected field is exposed via a property with a higher
  149. visibility, then we have to create a getter and/or setter with that same
  150. higher visibility to make sure that using the property does not result
  151. in JVM verification errors }
  152. function create_getter_or_setter_for_property(orgaccesspd: tprocdef; getter: boolean): tprocdef;
  153. procedure finalize_getter_or_setter_for_sym(getset: tpropaccesslisttypes; sym: tsym; fielddef: tdef; accessordef: tprocdef); override;
  154. procedure register_override(overriddenprop: tpropertysym); override;
  155. procedure maybe_create_overridden_getter_or_setter(getset: tpropaccesslisttypes);
  156. end;
  157. tcpupropertysymclass = class of tcpupropertysym;
  158. tcpuconstsym = class(tconstsym)
  159. end;
  160. tcpuconstsymclass = class of tcpuconstsym;
  161. tcpuenumsym = class(tenumsym)
  162. end;
  163. tcpuenumsymclass = class of tcpuenumsym;
  164. tcpusyssym = class(tsyssym)
  165. end;
  166. tcpusyssymclass = class of tcpusyssym;
  167. const
  168. pbestrealtype : ^tdef = @s64floattype;
  169. implementation
  170. uses
  171. verbose,cutils,cclasses,globals,
  172. symconst,symbase,symtable,symcreat,jvmdef,
  173. pdecsub,pjvm,
  174. paramgr;
  175. {****************************************************************************
  176. tcpuproptertysym
  177. ****************************************************************************}
  178. function tcpupropertysym.create_getter_or_setter_for_property(orgaccesspd: tprocdef; getter: boolean): tprocdef;
  179. var
  180. obj: tabstractrecorddef;
  181. ps: tprocsym;
  182. pvs: tparavarsym;
  183. sym: tsym;
  184. pd, parentpd, accessorparapd: tprocdef;
  185. tmpaccesslist: tpropaccesslist;
  186. callthroughpropname,
  187. accessorname: string;
  188. callthroughprop: tpropertysym;
  189. accesstyp: tpropaccesslisttypes;
  190. sktype: tsynthetickind;
  191. procoptions: tprocoptions;
  192. paranr: word;
  193. explicitwrapper: boolean;
  194. begin
  195. obj:=current_structdef;
  196. { if someone gets the idea to add a property to an external class
  197. definition, don't try to wrap it since we cannot add methods to
  198. external classes }
  199. if oo_is_external in obj.objectoptions then
  200. exit;
  201. symtablestack.push(obj.symtable);
  202. try
  203. if getter then
  204. accesstyp:=palt_read
  205. else
  206. accesstyp:=palt_write;
  207. { we can't use str_parse_method_dec here because the type of the field
  208. may not be visible at the Pascal level }
  209. explicitwrapper:=
  210. { private methods are not visibile outside the current class, so
  211. no use in making life harder for us by introducing potential
  212. (future or current) naming conflicts }
  213. (visibility<>vis_private) and
  214. (getter and
  215. (prop_auto_getter_prefix<>'')) or
  216. (not getter and
  217. (prop_auto_setter_prefix<>''));
  218. sym:=nil;
  219. procoptions:=[];
  220. if explicitwrapper then
  221. begin
  222. if getter then
  223. accessorname:=prop_auto_getter_prefix+realname
  224. else
  225. accessorname:=prop_auto_setter_prefix+realname;
  226. sym:=search_struct_member_no_helper(obj,upper(accessorname));
  227. if getter then
  228. sktype:=tsk_field_getter
  229. else
  230. sktype:=tsk_field_setter;
  231. if assigned(sym) then
  232. begin
  233. if ((sym.typ<>procsym) or
  234. (tprocsym(sym).procdeflist.count<>1) or
  235. (tprocdef(tprocsym(sym).procdeflist[0]).synthetickind<>sktype)) and
  236. (not assigned(orgaccesspd) or
  237. (sym<>orgaccesspd.procsym)) then
  238. begin
  239. MessagePos2(fileinfo,parser_e_cannot_generate_property_getter_setter,accessorname,FullTypeName(tdef(sym.owner.defowner),nil)+'.'+accessorname);
  240. exit;
  241. end
  242. else
  243. begin
  244. if accessorname<>sym.realname then
  245. MessagePos2(fileinfo,parser_w_case_difference_auto_property_getter_setter_prefix,sym.realname,accessorname);
  246. { is the specified getter/setter defined in the current
  247. struct and was it originally specified as the getter/
  248. setter for this property? If so, simply adjust its
  249. visibility if necessary.
  250. }
  251. if assigned(orgaccesspd) then
  252. parentpd:=orgaccesspd
  253. else
  254. parentpd:=tprocdef(tprocsym(sym).procdeflist[0]);
  255. if parentpd.owner.defowner=owner.defowner then
  256. begin
  257. if parentpd.visibility<visibility then
  258. begin
  259. parentpd.visibility:=visibility;
  260. include(parentpd.procoptions,po_auto_raised_visibility);
  261. end;
  262. result:=parentpd;
  263. { we are done, no need to create a wrapper }
  264. exit
  265. end
  266. { a parent already included this getter/setter -> try to
  267. override it }
  268. else if parentpd.visibility<>vis_private then
  269. begin
  270. if po_virtualmethod in parentpd.procoptions then
  271. begin
  272. procoptions:=procoptions+[po_virtualmethod,po_overridingmethod];
  273. if not(parentpd.synthetickind in [tsk_field_getter,tsk_field_setter]) then
  274. Message2(parser_w_overriding_property_getter_setter,accessorname,FullTypeName(tdef(parentpd.owner.defowner),nil));
  275. end;
  276. { otherwise we can't do anything, and
  277. proc_add_definition will give an error }
  278. end;
  279. { add method with the correct visibility }
  280. pd:=tprocdef(parentpd.getcopy);
  281. { get rid of the import accessorname for inherited virtual class methods,
  282. it has to be regenerated rather than amended }
  283. if [po_classmethod,po_virtualmethod]<=pd.procoptions then
  284. begin
  285. stringdispose(pd.import_name);
  286. exclude(pd.procoptions,po_has_importname);
  287. end;
  288. pd.visibility:=visibility;
  289. pd.procoptions:=pd.procoptions+procoptions;
  290. { ignore this artificially added procdef when looking for overloads }
  291. include(pd.procoptions,po_ignore_for_overload_resolution);
  292. finish_copied_procdef(pd,parentpd.procsym.realname,obj.symtable,obj);
  293. exclude(pd.procoptions,po_external);
  294. pd.synthetickind:=tsk_anon_inherited;
  295. result:=pd;
  296. exit;
  297. end;
  298. end;
  299. { make the artificial getter/setter virtual so we can override it in
  300. children if necessary }
  301. if not(sp_static in symoptions) and
  302. (obj.typ=objectdef) then
  303. include(procoptions,po_virtualmethod);
  304. { prevent problems in Delphi mode }
  305. include(procoptions,po_overload);
  306. end
  307. else
  308. begin
  309. { construct procsym accessorname (unique for this access; reusing the same
  310. helper for multiple accesses to the same field is hard because the
  311. propacesslist can contain subscript nodes etc) }
  312. accessorname:=visibilityName[visibility];
  313. replace(accessorname,' ','_');
  314. if getter then
  315. accessorname:=accessorname+'$getter'
  316. else
  317. accessorname:=accessorname+'$setter';
  318. end;
  319. { create procdef }
  320. if not assigned(orgaccesspd) then
  321. begin
  322. pd:=cprocdef.create(normal_function_level);
  323. if df_generic in obj.defoptions then
  324. include(pd.defoptions,df_generic);
  325. { method of this objectdef }
  326. pd.struct:=obj;
  327. { can only construct the artificial accessorname now, because it requires
  328. pd.defid }
  329. if not explicitwrapper then
  330. accessorname:='$'+obj.symtable.realname^+'$'+realname+'$'+accessorname+'$'+tostr(pd.defid);
  331. end
  332. else
  333. begin
  334. { getter/setter could have parameters in case of indexed access
  335. -> copy original procdef }
  336. pd:=tprocdef(orgaccesspd.getcopy);
  337. exclude(pd.procoptions,po_abstractmethod);
  338. exclude(pd.procoptions,po_overridingmethod);
  339. { can only construct the artificial accessorname now, because it requires
  340. pd.defid }
  341. if not explicitwrapper then
  342. accessorname:='$'+obj.symtable.realname^+'$'+realname+'$'+accessorname+'$'+tostr(pd.defid);
  343. finish_copied_procdef(pd,accessorname,obj.symtable,obj);
  344. sym:=pd.procsym;
  345. end;
  346. { add previously collected procoptions }
  347. pd.procoptions:=pd.procoptions+procoptions;
  348. { visibility }
  349. pd.visibility:=visibility;
  350. result:=pd;
  351. { new procsym? }
  352. if not assigned(sym) or
  353. (sym.owner<>owner) then
  354. begin
  355. ps:=cprocsym.create(accessorname);
  356. obj.symtable.insert(ps);
  357. end
  358. else
  359. ps:=tprocsym(sym);
  360. { associate procsym with procdef}
  361. pd.procsym:=ps;
  362. { function/procedure }
  363. accessorparapd:=nil;
  364. if getter then
  365. begin
  366. pd.proctypeoption:=potype_function;
  367. pd.synthetickind:=tsk_field_getter;
  368. { result type }
  369. pd.returndef:=propdef;
  370. if (ppo_hasparameters in propoptions) and
  371. not assigned(orgaccesspd) then
  372. accessorparapd:=pd;
  373. end
  374. else
  375. begin
  376. pd.proctypeoption:=potype_procedure;
  377. pd.synthetickind:=tsk_field_setter;
  378. pd.returndef:=voidtype;
  379. if not assigned(orgaccesspd) then
  380. begin
  381. { parameter with value to set }
  382. pvs:=cparavarsym.create('__fpc_newval__',10,vs_const,propdef,[]);
  383. pd.parast.insert(pvs);
  384. end;
  385. if (ppo_hasparameters in propoptions) and
  386. not assigned(orgaccesspd) then
  387. accessorparapd:=pd;
  388. end;
  389. { create a property for the old symaccesslist with a new accessorname, so that
  390. we can reuse it in the implementation (rather than having to
  391. translate the symaccesslist back to Pascal code) }
  392. callthroughpropname:='__fpc__'+realname;
  393. if getter then
  394. callthroughpropname:=callthroughpropname+'__getter_wrapper'
  395. else
  396. callthroughpropname:=callthroughpropname+'__setter_wrapper';
  397. callthroughprop:=cpropertysym.create(callthroughpropname);
  398. callthroughprop.visibility:=visibility;
  399. if getter then
  400. makeduplicate(callthroughprop,accessorparapd,nil,paranr)
  401. else
  402. makeduplicate(callthroughprop,nil,accessorparapd,paranr);
  403. callthroughprop.default:=longint($80000000);
  404. callthroughprop.default:=0;
  405. callthroughprop.propoptions:=callthroughprop.propoptions-[ppo_stored,ppo_enumerator_current,ppo_overrides,ppo_defaultproperty];
  406. if sp_static in symoptions then
  407. include(callthroughprop.symoptions, sp_static);
  408. { copy original property target to callthrough property (and replace
  409. original one with the new empty list; will be filled in later) }
  410. tmpaccesslist:=callthroughprop.propaccesslist[accesstyp];
  411. callthroughprop.propaccesslist[accesstyp]:=propaccesslist[accesstyp];
  412. propaccesslist[accesstyp]:=tmpaccesslist;
  413. owner.insert(callthroughprop);
  414. pd.skpara:=callthroughprop;
  415. { needs to be exported }
  416. include(pd.procoptions,po_global);
  417. { class property -> static class method }
  418. if sp_static in symoptions then
  419. pd.procoptions:=pd.procoptions+[po_classmethod,po_staticmethod];
  420. { in case we made a copy of the original accessor, this has all been
  421. done already }
  422. if not assigned(orgaccesspd) then
  423. begin
  424. { calling convention, self, ... }
  425. if obj.typ=recorddef then
  426. handle_calling_convention(pd,[hcc_check])
  427. else
  428. handle_calling_convention(pd,hcc_all);
  429. { register forward declaration with procsym }
  430. proc_add_definition(pd);
  431. end;
  432. { make the property call this new function }
  433. propaccesslist[accesstyp].addsym(sl_call,ps);
  434. propaccesslist[accesstyp].procdef:=pd;
  435. finally
  436. symtablestack.pop(obj.symtable);
  437. end;
  438. end;
  439. procedure tcpupropertysym.finalize_getter_or_setter_for_sym(getset: tpropaccesslisttypes; sym: tsym; fielddef: tdef; accessordef: tprocdef);
  440. var
  441. orgaccesspd, newaccesspd: tprocdef;
  442. pprefix: pshortstring;
  443. wrongvisibility: boolean;
  444. begin
  445. inherited;
  446. if getset=palt_read then
  447. pprefix:=@prop_auto_getter_prefix
  448. else
  449. pprefix:=@prop_auto_setter_prefix;
  450. newaccesspd:=nil;
  451. case sym.typ of
  452. procsym:
  453. begin
  454. orgaccesspd:=tprocdef(propaccesslist[getset].procdef);
  455. wrongvisibility:=tprocdef(propaccesslist[getset].procdef).visibility<visibility;
  456. { if the visibility of the accessor is lower than
  457. the visibility of the property, wrap it so that
  458. we can call it from all contexts in which the
  459. property is visible }
  460. if wrongvisibility or
  461. ((pprefix^<>'') and
  462. (sym.RealName<>pprefix^+RealName)) then
  463. newaccesspd:=create_getter_or_setter_for_property(orgaccesspd,getset=palt_read)
  464. end;
  465. fieldvarsym:
  466. begin
  467. { if the visibility of the field is lower than the
  468. visibility of the property, wrap it in a getter
  469. so that we can access it from all contexts in
  470. which the property is visibile }
  471. if (pprefix^<>'') or
  472. (tfieldvarsym(sym).visibility<visibility) then
  473. newaccesspd:=create_getter_or_setter_for_property(nil,getset=palt_read);
  474. end;
  475. else
  476. internalerror(2014061101);
  477. end;
  478. { update the getter/setter used for this property (already done in case
  479. a new method was created from scratch, but not if we overrode a
  480. getter/setter generated for the inherited property) }
  481. if assigned(newaccesspd) then
  482. begin
  483. if propaccesslist[getset].firstsym^.sym.typ<>procsym then
  484. internalerror(2014061201);
  485. propaccesslist[getset].procdef:=newaccesspd;
  486. propaccesslist[getset].firstsym^.sym:=newaccesspd.procsym;
  487. end;
  488. end;
  489. procedure tcpupropertysym.register_override(overriddenprop: tpropertysym);
  490. var
  491. sym: tsym;
  492. begin
  493. inherited;
  494. { new property has higher visibility than previous one -> maybe override
  495. the getters/setters }
  496. if (overriddenprop.visibility<visibility) then
  497. begin
  498. maybe_create_overridden_getter_or_setter(palt_read);
  499. maybe_create_overridden_getter_or_setter(palt_write);
  500. end;
  501. end;
  502. procedure tcpupropertysym.maybe_create_overridden_getter_or_setter(getset: tpropaccesslisttypes);
  503. var
  504. sym: tsym;
  505. fielddef: tdef;
  506. accessordef: tprocdef;
  507. psym: tpropertysym;
  508. begin
  509. { find the last defined getter/setter/field accessed by an inherited
  510. property }
  511. psym:=overriddenpropsym;
  512. while not assigned(psym.propaccesslist[getset].firstsym) do
  513. begin
  514. psym:=psym.overriddenpropsym;
  515. { if there is simply no getter/setter for this property, we're done }
  516. if not assigned(psym) then
  517. exit;
  518. end;
  519. sym:=psym.propaccesslist[getset].firstsym^.sym;
  520. case sym.typ of
  521. procsym:
  522. begin
  523. accessordef:=tprocdef(psym.propaccesslist[getset].procdef);
  524. if accessordef.visibility>=visibility then
  525. exit;
  526. fielddef:=nil;
  527. end;
  528. fieldvarsym:
  529. begin
  530. if sym.visibility>=visibility then
  531. exit;
  532. accessordef:=nil;
  533. fielddef:=tfieldvarsym(sym).vardef;
  534. end;
  535. else
  536. internalerror(2014061102);
  537. end;
  538. propaccesslist[getset]:=psym.propaccesslist[getset].getcopy;
  539. finalize_getter_or_setter_for_sym(getset,sym,propdef,accessordef);
  540. end;
  541. {****************************************************************************
  542. tcpuenumdef
  543. ****************************************************************************}
  544. procedure tcpuenumdef.ppuload_platform(ppufile: tcompilerppufile);
  545. begin
  546. inherited;
  547. ppufile.getderef(classdefderef);
  548. end;
  549. procedure tcpuenumdef.ppuwrite_platform(ppufile: tcompilerppufile);
  550. begin
  551. inherited;
  552. ppufile.putderef(classdefderef);
  553. end;
  554. function tcpuenumdef.getcopy: tstoreddef;
  555. begin
  556. result:=inherited;
  557. tcpuenumdef(result).classdef:=classdef;
  558. end;
  559. procedure tcpuenumdef.buildderef;
  560. begin
  561. inherited;
  562. classdefderef.build(classdef);
  563. end;
  564. procedure tcpuenumdef.deref;
  565. begin
  566. inherited;
  567. classdef:=tobjectdef(classdefderef.resolve);
  568. end;
  569. {****************************************************************************
  570. tcpuprocdef
  571. ****************************************************************************}
  572. function tcpuprocdef.jvmmangledbasename(signature: boolean): TSymStr;
  573. var
  574. vs: tparavarsym;
  575. i: longint;
  576. founderror: tdef;
  577. tmpresult: TSymStr;
  578. container: tsymtable;
  579. begin
  580. { format:
  581. * method definition (in Jasmin):
  582. (private|protected|public) [static] method(parametertypes)returntype
  583. * method invocation
  584. package/class/method(parametertypes)returntype
  585. -> store common part: method(parametertypes)returntype and
  586. adorn as required when using it.
  587. }
  588. if not signature then
  589. begin
  590. { method name }
  591. { special names for constructors and class constructors }
  592. if proctypeoption=potype_constructor then
  593. tmpresult:='<init>'
  594. else if proctypeoption in [potype_class_constructor,potype_unitinit] then
  595. tmpresult:='<clinit>'
  596. else if po_has_importname in procoptions then
  597. begin
  598. if assigned(import_name) then
  599. tmpresult:=import_name^
  600. else
  601. internalerror(2010122608);
  602. end
  603. else
  604. begin
  605. tmpresult:=procsym.realname;
  606. if tmpresult[1]='$' then
  607. tmpresult:=copy(tmpresult,2,length(tmpresult)-1);
  608. { nested functions }
  609. container:=owner;
  610. while container.symtabletype=localsymtable do
  611. begin
  612. tmpresult:='$'+tprocdef(owner.defowner).procsym.realname+'$'+tostr(tprocdef(owner.defowner).procsym.symid)+'$'+tmpresult;
  613. container:=container.defowner.owner;
  614. end;
  615. end;
  616. end
  617. else
  618. tmpresult:='';
  619. { parameter types }
  620. tmpresult:=tmpresult+'(';
  621. { not the case for the main program (not required for defaultmangledname
  622. because setmangledname() is called for the main program; in case of
  623. the JVM, this only sets the importname, however) }
  624. if assigned(paras) then
  625. begin
  626. init_paraloc_info(callerside);
  627. for i:=0 to paras.count-1 do
  628. begin
  629. vs:=tparavarsym(paras[i]);
  630. { function result is not part of the mangled name }
  631. if vo_is_funcret in vs.varoptions then
  632. continue;
  633. { self pointer neither, except for class methods (the JVM only
  634. supports static class methods natively, so the self pointer
  635. here is a regular parameter as far as the JVM is concerned }
  636. if not(po_classmethod in procoptions) and
  637. (vo_is_self in vs.varoptions) then
  638. continue;
  639. { passing by reference is emulated by passing an array of one
  640. element containing the value; for types that aren't pointers
  641. in regular Pascal, simply passing the underlying pointer type
  642. does achieve regular call-by-reference semantics though;
  643. formaldefs always have to be passed like that because their
  644. contents can be replaced }
  645. if paramanager.push_copyout_param(vs.varspez,vs.vardef,proccalloption) then
  646. tmpresult:=tmpresult+'[';
  647. { Add the parameter type. }
  648. if not jvmaddencodedtype(vs.vardef,false,tmpresult,signature,founderror) then
  649. { an internalerror here is also triggered in case of errors in the source code }
  650. tmpresult:='<error>';
  651. end;
  652. end;
  653. tmpresult:=tmpresult+')';
  654. { And the type of the function result (void in case of a procedure and
  655. constructor). }
  656. if (proctypeoption in [potype_constructor,potype_class_constructor]) then
  657. jvmaddencodedtype(voidtype,false,tmpresult,signature,founderror)
  658. else if not jvmaddencodedtype(returndef,false,tmpresult,signature,founderror) then
  659. { an internalerror here is also triggered in case of errors in the source code }
  660. tmpresult:='<error>';
  661. result:=tmpresult;
  662. end;
  663. function tcpuprocdef.mangledname: TSymStr;
  664. begin
  665. if _mangledname='' then
  666. begin
  667. result:=jvmmangledbasename(false);
  668. if (po_has_importdll in procoptions) then
  669. begin
  670. { import_dll comes from "external 'import_dll_name' name 'external_name'" }
  671. if assigned(import_dll) then
  672. result:=import_dll^+'/'+result
  673. else
  674. internalerror(2010122607);
  675. end
  676. else
  677. jvmaddtypeownerprefix(owner,mangledname);
  678. _mangledname:=result;
  679. end
  680. else
  681. result:=_mangledname;
  682. end;
  683. destructor tcpuprocdef.destroy;
  684. begin
  685. exprasmlist.free;
  686. inherited destroy;
  687. end;
  688. {****************************************************************************
  689. tcpuprocvardef
  690. ****************************************************************************}
  691. procedure tcpuprocvardef.ppuwrite_platform(ppufile: tcompilerppufile);
  692. begin
  693. inherited;
  694. ppufile.putderef(classdefderef);
  695. end;
  696. procedure tcpuprocvardef.ppuload_platform(ppufile: tcompilerppufile);
  697. begin
  698. inherited;
  699. ppufile.getderef(classdefderef);
  700. end;
  701. procedure tcpuprocvardef.buildderef;
  702. begin
  703. inherited buildderef;
  704. classdefderef.build(classdef);
  705. end;
  706. procedure tcpuprocvardef.deref;
  707. begin
  708. inherited deref;
  709. classdef:=tobjectdef(classdefderef.resolve);
  710. end;
  711. function tcpuprocvardef.getcopy: tstoreddef;
  712. begin
  713. result:=inherited;
  714. tcpuprocvardef(result).classdef:=classdef;
  715. end;
  716. {****************************************************************************
  717. tcpuprocsym
  718. ****************************************************************************}
  719. procedure tcpuprocsym.check_forward;
  720. var
  721. curri, checki: longint;
  722. currpd, checkpd: tprocdef;
  723. begin
  724. inherited;
  725. { check for conflicts based on mangled name, because several FPC
  726. types/constructs map to the same JVM mangled name }
  727. for curri:=0 to FProcdefList.Count-2 do
  728. begin
  729. currpd:=tprocdef(FProcdefList[curri]);
  730. if (po_external in currpd.procoptions) or
  731. (currpd.proccalloption=pocall_internproc) then
  732. continue;
  733. for checki:=curri+1 to FProcdefList.Count-1 do
  734. begin
  735. checkpd:=tprocdef(FProcdefList[checki]);
  736. if po_external in checkpd.procoptions then
  737. continue;
  738. if currpd.mangledname=checkpd.mangledname then
  739. begin
  740. MessagePos(checkpd.fileinfo,parser_e_overloaded_have_same_mangled_name);
  741. MessagePos1(currpd.fileinfo,sym_e_param_list,currpd.customprocname([pno_mangledname]));
  742. MessagePos1(checkpd.fileinfo,sym_e_param_list,checkpd.customprocname([pno_mangledname]));
  743. end;
  744. end;
  745. end;
  746. inherited;
  747. end;
  748. {****************************************************************************
  749. tcpustaticvarsym
  750. ****************************************************************************}
  751. procedure tcpustaticvarsym.set_mangledname(const s: TSymStr);
  752. begin
  753. inherited;
  754. _mangledname:=jvmmangledbasename(self,s,false);
  755. jvmaddtypeownerprefix(owner,_mangledname);
  756. end;
  757. function tcpustaticvarsym.mangledname: TSymStr;
  758. begin
  759. if _mangledname='' then
  760. begin
  761. if _mangledbasename='' then
  762. _mangledname:=jvmmangledbasename(self,false)
  763. else
  764. _mangledname:=jvmmangledbasename(self,_mangledbasename,false);
  765. jvmaddtypeownerprefix(owner,_mangledname);
  766. end;
  767. result:=_mangledname;
  768. end;
  769. {****************************************************************************
  770. tcpufieldvarsym
  771. ****************************************************************************}
  772. procedure tcpufieldvarsym.set_externalname(const s: string);
  773. begin
  774. { make sure it is recalculated }
  775. cachedmangledname:='';
  776. if is_java_class_or_interface(tdef(owner.defowner)) then
  777. begin
  778. externalname:=stringdup(s);
  779. include(varoptions,vo_has_mangledname);
  780. end
  781. else
  782. internalerror(2011031201);
  783. end;
  784. function tcpufieldvarsym.mangledname: TSymStr;
  785. begin
  786. if is_java_class_or_interface(tdef(owner.defowner)) or
  787. (tdef(owner.defowner).typ=recorddef) then
  788. begin
  789. if cachedmangledname<>'' then
  790. result:=cachedmangledname
  791. else
  792. begin
  793. result:=jvmmangledbasename(self,false);
  794. jvmaddtypeownerprefix(owner,result);
  795. cachedmangledname:=result;
  796. end;
  797. end
  798. else
  799. result:=inherited;
  800. end;
  801. begin
  802. { used tdef classes }
  803. cfiledef:=tcpufiledef;
  804. cvariantdef:=tcpuvariantdef;
  805. cformaldef:=tcpuformaldef;
  806. cforwarddef:=tcpuforwarddef;
  807. cundefineddef:=tcpuundefineddef;
  808. cerrordef:=tcpuerrordef;
  809. cpointerdef:=tcpupointerdef;
  810. crecorddef:=tcpurecorddef;
  811. cimplementedinterface:=tcpuimplementedinterface;
  812. cobjectdef:=tcpuobjectdef;
  813. cclassrefdef:=tcpuclassrefdef;
  814. carraydef:=tcpuarraydef;
  815. corddef:=tcpuorddef;
  816. cfloatdef:=tcpufloatdef;
  817. cprocvardef:=tcpuprocvardef;
  818. cprocdef:=tcpuprocdef;
  819. cstringdef:=tcpustringdef;
  820. cenumdef:=tcpuenumdef;
  821. csetdef:=tcpusetdef;
  822. { used tsym classes }
  823. clabelsym:=tcpulabelsym;
  824. cunitsym:=tcpuunitsym;
  825. cnamespacesym:=tcpunamespacesym;
  826. cprocsym:=tcpuprocsym;
  827. ctypesym:=tcputypesym;
  828. cfieldvarsym:=tcpufieldvarsym;
  829. clocalvarsym:=tcpulocalvarsym;
  830. cparavarsym:=tcpuparavarsym;
  831. cstaticvarsym:=tcpustaticvarsym;
  832. cabsolutevarsym:=tcpuabsolutevarsym;
  833. cpropertysym:=tcpupropertysym;
  834. cconstsym:=tcpuconstsym;
  835. cenumsym:=tcpuenumsym;
  836. csyssym:=tcpusyssym;
  837. end.