hlcgcpu.pas 62 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657
  1. {
  2. Copyright (c) 1998-2010 by Florian Klaempfl and Jonas Maebe
  3. Member of the Free Pascal development team
  4. This unit implements the jvm high level code generator
  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. unit hlcgcpu;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,
  23. aasmbase,aasmdata,
  24. symtype,symdef,
  25. cpubase, hlcgobj, cgbase, cgutils, parabase;
  26. type
  27. { thlcgjvm }
  28. thlcgjvm = class(thlcgobj)
  29. private
  30. fevalstackheight,
  31. fmaxevalstackheight: longint;
  32. public
  33. constructor create;
  34. procedure incstack(list : TAsmList;slots: longint);
  35. procedure decstack(list : TAsmList;slots: longint);
  36. procedure a_call_name(list : TAsmList;pd : tprocdef;const s : string; weak: boolean);override;
  37. procedure a_call_name_inherited(list : TAsmList;pd : tprocdef;const s : string);override;
  38. procedure a_load_const_reg(list : TAsmList;tosize : tdef;a : aint;register : tregister);override;
  39. procedure a_load_const_ref(list : TAsmList;tosize : tdef;a : aint;const ref : treference);override;
  40. procedure a_load_reg_ref(list : TAsmList;fromsize, tosize : tdef;register : tregister;const ref : treference);override;
  41. procedure a_load_reg_reg(list : TAsmList;fromsize, tosize : tdef;reg1,reg2 : tregister);override;
  42. procedure a_load_ref_reg(list : TAsmList;fromsize, tosize : tdef;const ref : treference;register : tregister);override;
  43. procedure a_load_ref_ref(list : TAsmList;fromsize, tosize : tdef;const sref : treference;const dref : treference);override;
  44. procedure a_loadaddr_ref_reg(list : TAsmList;fromsize, tosize : tdef;const ref : treference;r : tregister);override;
  45. procedure a_op_const_reg(list: TAsmList; Op: TOpCG; size: tdef; a: Aint; reg: TRegister); override;
  46. procedure a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tdef; a: aint; src, dst: tregister); override;
  47. procedure a_op_const_ref(list: TAsmList; Op: TOpCG; size: tdef; a: Aint; const ref: TReference); override;
  48. procedure a_op_ref_reg(list: TAsmList; Op: TOpCG; size: tdef; const ref: TReference; reg: TRegister); override;
  49. procedure a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tdef; src1, src2, dst: tregister); override;
  50. procedure a_op_reg_reg(list: TAsmList; Op: TOpCG; size: tdef; reg1, reg2: TRegister); override;
  51. procedure a_cmp_const_ref_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: aint; const ref: treference; l: tasmlabel); override;
  52. procedure a_cmp_const_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: aint; reg: tregister; l: tasmlabel); override;
  53. procedure a_cmp_ref_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; const ref: treference; reg: tregister; l: tasmlabel); override;
  54. procedure a_cmp_reg_ref_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg: tregister; const ref: treference; l: tasmlabel); override;
  55. procedure a_cmp_reg_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel); override;
  56. procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
  57. procedure g_concatcopy(list : TAsmList;size: tdef; const source,dest : treference);override;
  58. procedure a_loadfpu_ref_ref(list: TAsmList; fromsize, tosize: tdef; const ref1, ref2: treference); override;
  59. procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister); override;
  60. procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tdef; reg: tregister; const ref: treference); override;
  61. procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister); override;
  62. procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean); override;
  63. procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean); override;
  64. procedure gen_load_return_value(list:TAsmList);override;
  65. procedure record_generated_code_for_procdef(pd: tprocdef; code, data: TAsmList); override;
  66. procedure g_incrrefcount(list : TAsmList;t: tdef; const ref: treference);override;
  67. procedure g_decrrefcount(list : TAsmList;t: tdef; const ref: treference);override;
  68. procedure g_initialize(list : TAsmList;t : tdef;const ref : treference);override;
  69. procedure g_finalize(list : TAsmList;t : tdef;const ref : treference);override;
  70. procedure location_get_data_ref(list:TAsmList;def: tdef; const l:tlocation;var ref:treference;loadref:boolean; alignment: longint);override;
  71. procedure g_copyvaluepara_openarray(list: TAsmList; const ref: treference; const lenloc: tlocation; arrdef: tarraydef; destreg: tregister); override;
  72. procedure g_releasevaluepara_openarray(list: TAsmList; arrdef: tarraydef; const l: tlocation); override;
  73. { JVM-specific routines }
  74. procedure a_load_stack_reg(list : TAsmList;size: tdef;reg: tregister);
  75. { extra_slots are the slots that are used by the reference, and that
  76. will be removed by the store operation }
  77. procedure a_load_stack_ref(list : TAsmList;size: tdef;const ref: treference;extra_slots: longint);
  78. procedure a_load_reg_stack(list : TAsmList;size: tdef;reg: tregister);
  79. { extra_slots are the slots that are used by the reference, and that
  80. will be removed by the load operation }
  81. procedure a_load_ref_stack(list : TAsmList;size: tdef;const ref: treference;extra_slots: longint);
  82. procedure a_load_const_stack(list : TAsmList;size: tdef;a :aint; typ: TRegisterType);
  83. procedure a_load_stack_loc(list : TAsmList;size: tdef;const loc: tlocation);
  84. procedure a_load_loc_stack(list : TAsmList;size: tdef;const loc: tlocation);
  85. procedure a_loadfpu_const_stack(list : TAsmList;size: tdef;a :double);
  86. procedure a_op_stack(list : TAsmList;op: topcg; size: tdef; trunc32: boolean);
  87. procedure a_op_const_stack(list : TAsmList;op: topcg; size: tdef;a : aint);
  88. procedure a_op_reg_stack(list : TAsmList;op: topcg; size: tdef;reg: tregister);
  89. procedure a_op_ref_stack(list : TAsmList;op: topcg; size: tdef;const ref: treference);
  90. procedure a_op_loc_stack(list : TAsmList;op: topcg; size: tdef;const loc: tlocation);
  91. procedure g_reference_loc(list: TAsmList; def: tdef; const fromloc: tlocation; out toloc: tlocation); override;
  92. { assumes that initdim dimensions have already been pushed on the
  93. evaluation stack, and creates a new array of type arrdef with these
  94. dimensions }
  95. procedure g_newarray(list : TAsmList; arrdef: tdef; initdim: longint);
  96. { gets the length of the array whose reference is stored in arrloc,
  97. and puts it on the evaluation stack }
  98. procedure g_getarraylen(list : TAsmList; const arrloc: tlocation);
  99. { this routine expects that all values are already massaged into the
  100. required form (sign bits xor'ed for gt/lt comparisons for OS_32/OS_64,
  101. see http://stackoverflow.com/questions/4068973/c-performing-signed-comparison-in-unsigned-variables-without-casting ) }
  102. procedure a_cmp_stack_label(list : TAsmlist; size: tdef; cmp_op: topcmp; lab: tasmlabel);
  103. { these 2 routines perform the massaging expected by the previous one }
  104. procedure maybe_adjust_cmp_stackval(list : TAsmlist; size: tdef; cmp_op: topcmp);
  105. function maybe_adjust_cmp_constval(size: tdef; cmp_op: topcmp; a: aint): aint;
  106. { truncate/sign extend after performing operations on values < 32 bit
  107. that may have overflowed outside the range }
  108. procedure maybe_adjust_op_result(list: TAsmList; op: TOpCg; size: tdef);
  109. { performs sign/zero extension as required }
  110. procedure resize_stack_int_val(list: TAsmList;fromsize,tosize: tcgsize; forarraystore: boolean);
  111. property maxevalstackheight: longint read fmaxevalstackheight;
  112. protected
  113. procedure gen_load_uninitialized_function_result(list: TAsmList; pd: tprocdef; resdef: tdef; const resloc: tcgpara); override;
  114. { in case of an array, the array base address and index have to be
  115. put on the evaluation stack before the stored value; similarly, for
  116. fields the self pointer has to be loaded first. Also checks whether
  117. the reference is valid. If dup is true, the necessary values are stored
  118. twice. Returns how many stack slots have been consumed, disregarding
  119. the "dup". }
  120. function prepare_stack_for_ref(list: TAsmList; const ref: treference; dup: boolean): longint;
  121. { return the load/store opcode to load/store from/to ref; if the result
  122. has to be and'ed after a load to get the final value, that constant
  123. is returned in finishandval (otherwise that value is set to -1) }
  124. function loadstoreopcref(def: tdef; isload: boolean; const ref: treference; out finishandval: aint): tasmop;
  125. { return the load/store opcode to load/store from/to reg; if the result
  126. has to be and'ed after a load to get the final value, that constant
  127. is returned in finishandval (otherwise that value is set to -1) }
  128. function loadstoreopc(def: tdef; isload, isarray: boolean; out finishandval: aint): tasmop;
  129. procedure resizestackfpuval(list: TAsmList; fromsize, tosize: tcgsize);
  130. { in case of an OS_32 OP_DIV, we have to use an OS_S64 OP_IDIV because the
  131. JVM does not support unsigned divisions }
  132. procedure maybepreparedivu32(list: TAsmList; var op: topcg; size: tdef; out isdivu32: boolean);
  133. { common implementation of a_call_* }
  134. procedure a_call_name_intern(list : TAsmList;pd : tprocdef;const s : string; inheritedcall: boolean);
  135. { concatcopy helpers }
  136. procedure concatcopy_normal_array(list: TAsmList; size: tdef; const source, dest: treference);
  137. end;
  138. procedure create_hlcodegen;
  139. const
  140. opcmp2if: array[topcmp] of tasmop = (A_None,
  141. a_ifeq,a_ifgt,a_iflt,a_ifge,a_ifle,
  142. a_ifne,a_ifle,a_iflt,a_ifge,a_ifgt);
  143. implementation
  144. uses
  145. verbose,cutils,globals,
  146. defutil,
  147. aasmtai,aasmcpu,
  148. symconst,symtable,symsym,jvmdef,
  149. procinfo,cgcpu,tgobj;
  150. const
  151. TOpCG2IAsmOp : array[topcg] of TAsmOp=( { not = xor -1 }
  152. A_None,A_None,a_iadd,a_iand,A_none,a_idiv,a_imul,a_imul,a_ineg,A_None,a_ior,a_ishr,a_ishl,a_iushr,a_isub,a_ixor,A_None,A_None
  153. );
  154. TOpCG2LAsmOp : array[topcg] of TAsmOp=( { not = xor -1 }
  155. A_None,A_None,a_ladd,a_land,A_none,a_ldiv,a_lmul,a_lmul,a_lneg,A_None,a_lor,a_lshr,a_lshl,a_lushr,a_lsub,a_lxor,A_None,A_None
  156. );
  157. constructor thlcgjvm.create;
  158. begin
  159. fevalstackheight:=0;
  160. fmaxevalstackheight:=0;
  161. end;
  162. procedure thlcgjvm.incstack(list: TasmList;slots: longint);
  163. begin
  164. if slots=0 then
  165. exit;
  166. inc(fevalstackheight,slots);
  167. if (fevalstackheight>fmaxevalstackheight) then
  168. fmaxevalstackheight:=fevalstackheight;
  169. if cs_asm_regalloc in current_settings.globalswitches then
  170. list.concat(tai_comment.Create(strpnew('allocated '+tostr(slots)+', stack height = '+tostr(fevalstackheight))));
  171. end;
  172. procedure thlcgjvm.decstack(list: TAsmList;slots: longint);
  173. begin
  174. if slots=0 then
  175. exit;
  176. dec(fevalstackheight,slots);
  177. if (fevalstackheight<0) then
  178. internalerror(2010120501);
  179. if cs_asm_regalloc in current_settings.globalswitches then
  180. list.concat(tai_comment.Create(strpnew(' freed '+tostr(slots)+', stack height = '+tostr(fevalstackheight))));
  181. end;
  182. procedure thlcgjvm.a_call_name(list: TAsmList; pd: tprocdef; const s: string; weak: boolean);
  183. begin
  184. a_call_name_intern(list,pd,s,false);
  185. end;
  186. procedure thlcgjvm.a_call_name_inherited(list: TAsmList; pd: tprocdef; const s: string);
  187. begin
  188. a_call_name_intern(list,pd,s,true);
  189. end;
  190. procedure thlcgjvm.a_load_const_stack(list : TAsmList;size : tdef;a : aint; typ: TRegisterType);
  191. const
  192. int2opc: array[-1..5] of tasmop = (a_iconst_m1,a_iconst_0,a_iconst_1,
  193. a_iconst_2,a_iconst_3,a_iconst_4,a_iconst_5);
  194. begin
  195. case typ of
  196. R_INTREGISTER:
  197. begin
  198. case def_cgsize(size) of
  199. OS_8,OS_16,OS_32,
  200. OS_S8,OS_S16,OS_S32:
  201. begin
  202. { convert cardinals to longints }
  203. a:=longint(a);
  204. if (a>=-1) and
  205. (a<=5) then
  206. list.concat(taicpu.op_none(int2opc[a]))
  207. else if (a>=low(shortint)) and
  208. (a<=high(shortint)) then
  209. list.concat(taicpu.op_const(a_bipush,a))
  210. else if (a>=low(smallint)) and
  211. (a<=high(smallint)) then
  212. list.concat(taicpu.op_const(a_sipush,a))
  213. else
  214. list.concat(taicpu.op_const(a_ldc,a));
  215. end;
  216. OS_64,OS_S64:
  217. begin
  218. case a of
  219. 0:
  220. list.concat(taicpu.op_none(a_lconst_0));
  221. 1:
  222. list.concat(taicpu.op_none(a_lconst_1));
  223. else
  224. list.concat(taicpu.op_const(a_ldc2_w,a));
  225. end;
  226. incstack(list,1);
  227. end;
  228. else
  229. internalerror(2010110702);
  230. end;
  231. end;
  232. R_ADDRESSREGISTER:
  233. begin
  234. if a<>0 then
  235. internalerror(2010110701);
  236. list.concat(taicpu.op_none(a_aconst_null));
  237. end;
  238. else
  239. internalerror(2010110703);
  240. end;
  241. incstack(list,1);
  242. end;
  243. procedure thlcgjvm.a_load_stack_loc(list: TAsmList; size: tdef; const loc: tlocation);
  244. begin
  245. case loc.loc of
  246. LOC_REGISTER,LOC_CREGISTER,
  247. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  248. a_load_stack_reg(list,size,loc.register);
  249. LOC_REFERENCE:
  250. a_load_stack_ref(list,size,loc.reference,prepare_stack_for_ref(list,loc.reference,false));
  251. else
  252. internalerror(2011020501);
  253. end;
  254. end;
  255. procedure thlcgjvm.a_load_loc_stack(list: TAsmList;size: tdef;const loc: tlocation);
  256. begin
  257. case loc.loc of
  258. LOC_REGISTER,LOC_CREGISTER,
  259. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  260. a_load_reg_stack(list,size,loc.register);
  261. LOC_REFERENCE,LOC_CREFERENCE:
  262. a_load_ref_stack(list,size,loc.reference,prepare_stack_for_ref(list,loc.reference,false));
  263. LOC_CONSTANT:
  264. a_load_const_stack(list,size,loc.value,def2regtyp(size));
  265. else
  266. internalerror(2011010401);
  267. end;
  268. end;
  269. procedure thlcgjvm.a_loadfpu_const_stack(list: TAsmList; size: tdef; a: double);
  270. begin
  271. case tfloatdef(size).floattype of
  272. s32real:
  273. begin
  274. if a=0.0 then
  275. list.concat(taicpu.op_none(a_fconst_0))
  276. else if a=1.0 then
  277. list.concat(taicpu.op_none(a_fconst_1))
  278. else if a=2.0 then
  279. list.concat(taicpu.op_none(a_fconst_2))
  280. else
  281. list.concat(taicpu.op_single(a_ldc,a));
  282. incstack(list,1);
  283. end;
  284. s64real:
  285. begin
  286. if a=0.0 then
  287. list.concat(taicpu.op_none(a_dconst_0))
  288. else if a=1.0 then
  289. list.concat(taicpu.op_none(a_dconst_1))
  290. else
  291. list.concat(taicpu.op_double(a_ldc2_w,a));
  292. incstack(list,2);
  293. end
  294. else
  295. internalerror(2011010501);
  296. end;
  297. end;
  298. procedure thlcgjvm.a_op_stack(list: TAsmList; op: topcg; size: tdef; trunc32: boolean);
  299. var
  300. cgsize: tcgsize;
  301. begin
  302. if not trunc32 then
  303. cgsize:=def_cgsize(size)
  304. else
  305. begin
  306. resize_stack_int_val(list,OS_32,OS_S64,false);
  307. cgsize:=OS_S64;
  308. end;
  309. case cgsize of
  310. OS_8,OS_S8,
  311. OS_16,OS_S16,
  312. OS_32,OS_S32:
  313. begin
  314. { not = xor 1 for boolean, xor -1 for the rest}
  315. if op=OP_NOT then
  316. begin
  317. if not is_pasbool(size) then
  318. a_load_const_stack(list,s32inttype,high(cardinal),R_INTREGISTER)
  319. else
  320. a_load_const_stack(list,size,1,R_INTREGISTER);
  321. op:=OP_XOR;
  322. end;
  323. if TOpCG2IAsmOp[op]=A_None then
  324. internalerror(2010120532);
  325. list.concat(taicpu.op_none(TOpCG2IAsmOp[op]));
  326. maybe_adjust_op_result(list,op,size);
  327. if op<>OP_NEG then
  328. decstack(list,1);
  329. end;
  330. OS_64,OS_S64:
  331. begin
  332. { unsigned 64 bit division must be done via a helper }
  333. if op=OP_DIV then
  334. internalerror(2010120530);
  335. { not = xor -1 }
  336. if op=OP_NOT then
  337. begin
  338. a_load_const_stack(list,s64inttype,-1,R_INTREGISTER);
  339. op:=OP_XOR;
  340. end;
  341. if TOpCG2LAsmOp[op]=A_None then
  342. internalerror(2010120533);
  343. list.concat(taicpu.op_none(TOpCG2LAsmOp[op]));
  344. case op of
  345. OP_NOT:
  346. ;
  347. { the second argument here is an int rather than a long }
  348. OP_SHL,OP_SHR,OP_SAR:
  349. decstack(list,1);
  350. else
  351. decstack(list,2);
  352. end;
  353. end;
  354. else
  355. internalerror(2010120531);
  356. end;
  357. if trunc32 then
  358. begin
  359. list.concat(taicpu.op_none(a_l2i));
  360. decstack(list,1);
  361. end;
  362. end;
  363. procedure thlcgjvm.a_op_const_stack(list: TAsmList;op: topcg;size: tdef;a: aint);
  364. var
  365. trunc32: boolean;
  366. begin
  367. { use "integer to (wide)char" narrowing opcode for "and 65535" }
  368. if (op=OP_AND) and
  369. (def_cgsize(size) in [OS_16,OS_S16,OS_32,OS_S32]) and
  370. (a=65535) then
  371. list.concat(taicpu.op_none(a_i2c))
  372. else
  373. begin
  374. maybepreparedivu32(list,op,size,trunc32);
  375. case op of
  376. OP_NEG,OP_NOT:
  377. internalerror(2011010801);
  378. OP_SHL,OP_SHR,OP_SAR:
  379. { the second argument here is an int rather than a long }
  380. a_load_const_stack(list,s32inttype,a,R_INTREGISTER);
  381. else
  382. a_load_const_stack(list,size,a,R_INTREGISTER);
  383. end;
  384. a_op_stack(list,op,size,trunc32);
  385. end;
  386. end;
  387. procedure thlcgjvm.a_op_reg_stack(list: TAsmList; op: topcg; size: tdef; reg: tregister);
  388. var
  389. trunc32: boolean;
  390. begin
  391. maybepreparedivu32(list,op,size,trunc32);
  392. case op of
  393. OP_NEG,OP_NOT:
  394. ;
  395. OP_SHL,OP_SHR,OP_SAR:
  396. if not is_64bitint(size) then
  397. a_load_reg_stack(list,size,reg)
  398. else
  399. begin
  400. { the second argument here is an int rather than a long }
  401. if getsubreg(reg)=R_SUBQ then
  402. internalerror(2011010802);
  403. a_load_reg_stack(list,s32inttype,reg)
  404. end
  405. else
  406. a_load_reg_stack(list,size,reg);
  407. end;
  408. a_op_stack(list,op,size,trunc32);
  409. end;
  410. procedure thlcgjvm.a_op_ref_stack(list: TAsmList; op: topcg; size: tdef; const ref: treference);
  411. var
  412. trunc32: boolean;
  413. begin
  414. { ref must not be the stack top, because that may indicate an error
  415. (it means that we will perform an operation of the stack top onto
  416. itself, so that means the two values have been loaded manually prior
  417. to calling this routine, instead of letting this routine load one of
  418. them; if something like that is needed, call a_op_stack() directly) }
  419. if ref.base=NR_EVAL_STACK_BASE then
  420. internalerror(2010121102);
  421. maybepreparedivu32(list,op,size,trunc32);
  422. if not(op in [OP_NEG,OP_NOT]) then
  423. a_load_ref_stack(list,size,ref,prepare_stack_for_ref(list,ref,false));
  424. a_op_stack(list,op,size,trunc32);
  425. end;
  426. procedure thlcgjvm.a_op_loc_stack(list: TAsmList; op: topcg; size: tdef; const loc: tlocation);
  427. begin
  428. case loc.loc of
  429. LOC_REGISTER,LOC_CREGISTER:
  430. a_op_reg_stack(list,op,size,loc.register);
  431. LOC_REFERENCE,LOC_CREFERENCE:
  432. a_op_ref_stack(list,op,size,loc.reference);
  433. LOC_CONSTANT:
  434. a_op_const_stack(list,op,size,loc.value);
  435. else
  436. internalerror(2011011415)
  437. end;
  438. end;
  439. procedure thlcgjvm.g_reference_loc(list: TAsmList; def: tdef; const fromloc: tlocation; out toloc: tlocation);
  440. procedure handle_reg_move(regsize: tdef; const fromreg: tregister; out toreg: tregister; regtyp: tregistertype);
  441. begin
  442. case regtyp of
  443. R_INTREGISTER:
  444. toreg:=getintregister(list,regsize);
  445. R_ADDRESSREGISTER:
  446. toreg:=getaddressregister(list,regsize);
  447. R_FPUREGISTER:
  448. toreg:=getfpuregister(list,regsize);
  449. end;
  450. a_load_reg_reg(list,regsize,regsize,fromreg,toreg);
  451. end;
  452. begin
  453. toloc:=fromloc;
  454. case fromloc.loc of
  455. { volatile location, can't get a permanent reference }
  456. LOC_REGISTER,
  457. LOC_FPUREGISTER:
  458. internalerror(2011031406);
  459. LOC_CONSTANT:
  460. { finished }
  461. ;
  462. LOC_CREGISTER:
  463. handle_reg_move(def,fromloc.reference.index,toloc.reference.index,R_INTREGISTER);
  464. LOC_CFPUREGISTER:
  465. handle_reg_move(def,fromloc.reference.index,toloc.reference.index,R_FPUREGISTER);
  466. { although LOC_CREFERENCE cannot be an lvalue, we may want to take a
  467. reference to such a location for multiple reading }
  468. LOC_CREFERENCE,
  469. LOC_REFERENCE:
  470. begin
  471. if (fromloc.reference.base<>NR_NO) and
  472. (fromloc.reference.base<>current_procinfo.framepointer) and
  473. (fromloc.reference.base<>NR_STACK_POINTER_REG) then
  474. handle_reg_move(java_jlobject,fromloc.reference.base,toloc.reference.base,R_ADDRESSREGISTER);
  475. case fromloc.reference.arrayreftype of
  476. art_indexreg:
  477. begin
  478. { all array indices in Java are 32 bit ints }
  479. handle_reg_move(s32inttype,fromloc.reference.index,toloc.reference.index,R_INTREGISTER);
  480. end;
  481. art_indexref:
  482. begin
  483. if (fromloc.reference.indexbase<>NR_NO) and
  484. (fromloc.reference.indexbase<>NR_STACK_POINTER_REG) then
  485. handle_reg_move(s32inttype,fromloc.reference.indexbase,toloc.reference.indexbase,R_ADDRESSREGISTER);
  486. end;
  487. end;
  488. end;
  489. else
  490. internalerror(2011031407);
  491. end;
  492. end;
  493. procedure thlcgjvm.g_newarray(list: TAsmList; arrdef: tdef; initdim: longint);
  494. var
  495. recref: treference;
  496. elemdef: tdef;
  497. i: longint;
  498. mangledname: string;
  499. opc: tasmop;
  500. primitivetype: boolean;
  501. begin
  502. elemdef:=arrdef;
  503. if initdim>1 then
  504. begin
  505. { multianewarray typedesc ndim }
  506. list.concat(taicpu.op_sym_const(a_multianewarray,
  507. current_asmdata.RefAsmSymbol(jvmarrtype(elemdef,primitivetype)),initdim));
  508. { has to be a multi-dimensional array type }
  509. if primitivetype then
  510. internalerror(2011012207);
  511. end
  512. else
  513. begin
  514. { for primitive types:
  515. newarray typedesc
  516. for reference types:
  517. anewarray typedesc
  518. }
  519. { get the type of the elements of the array we are creating }
  520. elemdef:=tarraydef(arrdef).elementdef;
  521. mangledname:=jvmarrtype(elemdef,primitivetype);
  522. if primitivetype then
  523. opc:=a_newarray
  524. else
  525. opc:=a_anewarray;
  526. list.concat(taicpu.op_sym(opc,current_asmdata.RefAsmSymbol(mangledname)));
  527. end;
  528. { all dimensions are removed from the stack, an array reference is
  529. added }
  530. decstack(list,initdim-1);
  531. { in case of an array of records, initialise }
  532. elemdef:=tarraydef(arrdef).elementdef;
  533. for i:=1 to pred(initdim) do
  534. elemdef:=tarraydef(elemdef).elementdef;
  535. if elemdef.typ=recorddef then
  536. begin
  537. { duplicate array reference }
  538. list.concat(taicpu.op_none(a_dup));
  539. incstack(list,1);
  540. a_load_const_stack(list,s32inttype,initdim-1,R_INTREGISTER);
  541. tg.gethltemp(list,elemdef,elemdef.size,tt_persistent,recref);
  542. a_load_ref_stack(list,elemdef,recref,prepare_stack_for_ref(list,recref,false));
  543. g_call_system_proc(list,'fpc_initialize_array_record');
  544. tg.ungettemp(list,recref);
  545. decstack(list,3);
  546. end;
  547. end;
  548. procedure thlcgjvm.g_getarraylen(list: TAsmList; const arrloc: tlocation);
  549. var
  550. nillab,endlab: tasmlabel;
  551. begin
  552. { inline because we have to use the arraylength opcode, which
  553. cannot be represented directly in Pascal. Even though the JVM
  554. supports allocated arrays with length=0, we still also have to
  555. check for nil pointers because even if FPC always generates
  556. allocated empty arrays under all circumstances, external Java
  557. code could pass in nil pointers.
  558. Note that this means that assigned(arr) can be different from
  559. length(arr)<>0 for dynamic arrays when targeting the JVM.
  560. }
  561. current_asmdata.getjumplabel(nillab);
  562. current_asmdata.getjumplabel(endlab);
  563. { if assigned(arr) ... }
  564. a_load_loc_stack(list,java_jlobject,arrloc);
  565. list.concat(taicpu.op_none(a_dup));
  566. incstack(list,1);
  567. list.concat(taicpu.op_none(a_aconst_null));
  568. incstack(list,1);
  569. list.concat(taicpu.op_sym(a_if_acmpeq,nillab));
  570. decstack(list,2);
  571. { ... then result:=arraylength(arr) ... }
  572. list.concat(taicpu.op_none(a_arraylength));
  573. a_jmp_always(list,endlab);
  574. { ... else result:=0 }
  575. a_label(list,nillab);
  576. list.concat(taicpu.op_none(a_pop));
  577. decstack(list,1);
  578. list.concat(taicpu.op_none(a_iconst_0));
  579. incstack(list,1);
  580. a_label(list,endlab);
  581. end;
  582. procedure thlcgjvm.a_cmp_stack_label(list: TAsmlist; size: tdef; cmp_op: topcmp; lab: tasmlabel);
  583. const
  584. opcmp2icmp: array[topcmp] of tasmop = (A_None,
  585. a_if_icmpeq,a_if_icmpgt,a_if_icmplt,a_if_icmpge,a_if_icmple,
  586. a_if_icmpne,a_if_icmple,a_if_icmplt,a_if_icmpge,a_if_icmpgt);
  587. var
  588. cgsize: tcgsize;
  589. begin
  590. case def2regtyp(size) of
  591. R_INTREGISTER:
  592. begin
  593. cgsize:=def_cgsize(size);
  594. case cgsize of
  595. OS_S8,OS_8,
  596. OS_16,OS_S16,
  597. OS_S32,OS_32:
  598. begin
  599. list.concat(taicpu.op_sym(opcmp2icmp[cmp_op],lab));
  600. decstack(list,2);
  601. end;
  602. OS_64,OS_S64:
  603. begin
  604. list.concat(taicpu.op_none(a_lcmp));
  605. decstack(list,3);
  606. list.concat(taicpu.op_sym(opcmp2if[cmp_op],lab));
  607. decstack(list,1);
  608. end;
  609. else
  610. internalerror(2010120538);
  611. end;
  612. end;
  613. R_ADDRESSREGISTER:
  614. begin
  615. case cmp_op of
  616. OC_EQ:
  617. list.concat(taicpu.op_sym(a_if_acmpeq,lab));
  618. OC_NE:
  619. list.concat(taicpu.op_sym(a_if_acmpne,lab));
  620. else
  621. internalerror(2010120537);
  622. end;
  623. decstack(list,2);
  624. end;
  625. else
  626. internalerror(2010120538);
  627. end;
  628. end;
  629. procedure thlcgjvm.maybe_adjust_cmp_stackval(list: TAsmlist; size: tdef; cmp_op: topcmp);
  630. begin
  631. if (cmp_op in [OC_EQ,OC_NE]) or
  632. (def2regtyp(size)<>R_INTREGISTER) then
  633. exit;
  634. { http://stackoverflow.com/questions/4068973/c-performing-signed-comparison-in-unsigned-variables-without-casting }
  635. case def_cgsize(size) of
  636. OS_32:
  637. a_op_const_stack(list,OP_XOR,size,cardinal($80000000));
  638. OS_64:
  639. a_op_const_stack(list,OP_XOR,size,aint($8000000000000000));
  640. end;
  641. end;
  642. function thlcgjvm.maybe_adjust_cmp_constval(size: tdef; cmp_op: topcmp; a: aint): aint;
  643. begin
  644. result:=a;
  645. if (cmp_op in [OC_EQ,OC_NE]) or
  646. (def2regtyp(size)<>R_INTREGISTER) then
  647. exit;
  648. case def_cgsize(size) of
  649. OS_32:
  650. result:=a xor cardinal($80000000);
  651. OS_64:
  652. result:=a xor aint($8000000000000000);
  653. end;
  654. end;
  655. procedure thlcgjvm.maybe_adjust_op_result(list: TAsmList; op: TOpCg; size: tdef);
  656. const
  657. overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
  658. begin
  659. if (op in overflowops) and
  660. (def_cgsize(size) in [OS_8,OS_S8,OS_16,OS_S16]) then
  661. resize_stack_int_val(list,OS_S32,def_cgsize(size),false);
  662. end;
  663. procedure thlcgjvm.gen_load_uninitialized_function_result(list: TAsmList; pd: tprocdef; resdef: tdef; const resloc: tcgpara);
  664. begin
  665. { constructors don't return anything in Java }
  666. if pd.proctypeoption=potype_constructor then
  667. exit;
  668. { must return a value of the correct type on the evaluation stack }
  669. case def2regtyp(resdef) of
  670. R_INTREGISTER,
  671. R_ADDRESSREGISTER:
  672. a_load_const_cgpara(list,resdef,0,resloc);
  673. R_FPUREGISTER:
  674. case tfloatdef(resdef).floattype of
  675. s32real:
  676. list.concat(taicpu.op_none(a_fconst_0));
  677. s64real:
  678. list.concat(taicpu.op_none(a_dconst_0));
  679. else
  680. internalerror(2011010302);
  681. end
  682. else
  683. internalerror(2011010301);
  684. end;
  685. end;
  686. function thlcgjvm.prepare_stack_for_ref(list: TAsmList; const ref: treference; dup: boolean): longint;
  687. var
  688. href: treference;
  689. begin
  690. result:=0;
  691. { fake location that indicates the value is already on the stack? }
  692. if (ref.base=NR_EVAL_STACK_BASE) then
  693. exit;
  694. if ref.arrayreftype=art_none then
  695. begin
  696. { non-array accesses cannot have an index reg }
  697. if ref.index<>NR_NO then
  698. internalerror(2010120509);
  699. if (ref.base<>NR_NO) then
  700. begin
  701. if (ref.base<>NR_STACK_POINTER_REG) then
  702. begin
  703. { regular field -> load self on the stack }
  704. a_load_reg_stack(list,voidpointertype,ref.base);
  705. if dup then
  706. begin
  707. list.concat(taicpu.op_none(a_dup));
  708. incstack(list,1);
  709. end;
  710. { field name/type encoded in symbol, no index/offset }
  711. if not assigned(ref.symbol) or
  712. (ref.offset<>0) then
  713. internalerror(2010120524);
  714. result:=1;
  715. end
  716. else
  717. begin
  718. { local variable -> offset encoded in opcode and nothing to
  719. do here, except for checking that it's a valid reference }
  720. if assigned(ref.symbol) then
  721. internalerror(2010120523);
  722. end;
  723. end
  724. else
  725. begin
  726. { static field -> nothing to do here, except for validity check }
  727. if not assigned(ref.symbol) or
  728. (ref.offset<>0) then
  729. internalerror(2010120525);
  730. end;
  731. end
  732. else
  733. begin
  734. { arrays have implicit dereference -> pointer to array must have been
  735. loaded into base reg }
  736. if (ref.base=NR_NO) or
  737. (ref.base=NR_STACK_POINTER_REG) then
  738. internalerror(2010120511);
  739. if assigned(ref.symbol) then
  740. internalerror(2010120512);
  741. { stack: ... -> ..., arrayref, index }
  742. { load array base address }
  743. a_load_reg_stack(list,voidpointertype,ref.base);
  744. { index can either be in a register, or located in a simple memory
  745. location (since we have to load it anyway) }
  746. case ref.arrayreftype of
  747. art_indexreg:
  748. begin
  749. if ref.index=NR_NO then
  750. internalerror(2010120513);
  751. { all array indices in Java are 32 bit ints }
  752. a_load_reg_stack(list,s32inttype,ref.index);
  753. end;
  754. art_indexref:
  755. begin
  756. reference_reset_base(href,ref.indexbase,ref.indexoffset,4);
  757. href.symbol:=ref.indexsymbol;
  758. a_load_ref_stack(list,s32inttype,href,prepare_stack_for_ref(list,href,false));
  759. end;
  760. art_indexconst:
  761. begin
  762. a_load_const_stack(list,s32inttype,ref.indexoffset,R_INTREGISTER);
  763. end;
  764. else
  765. internalerror(2011012001);
  766. end;
  767. { adjustment of the index }
  768. if ref.offset<>0 then
  769. a_op_const_stack(list,OP_ADD,s32inttype,ref.offset);
  770. if dup then
  771. begin
  772. list.concat(taicpu.op_none(a_dup2));
  773. incstack(list,2);
  774. end;
  775. result:=2;
  776. end;
  777. end;
  778. procedure thlcgjvm.a_load_const_reg(list: TAsmList; tosize: tdef; a: aint; register: tregister);
  779. begin
  780. a_load_const_stack(list,tosize,a,def2regtyp(tosize));
  781. a_load_stack_reg(list,tosize,register);
  782. end;
  783. procedure thlcgjvm.a_load_const_ref(list: TAsmList; tosize: tdef; a: aint; const ref: treference);
  784. var
  785. extra_slots: longint;
  786. begin
  787. extra_slots:=prepare_stack_for_ref(list,ref,false);
  788. a_load_const_stack(list,tosize,a,def2regtyp(tosize));
  789. a_load_stack_ref(list,tosize,ref,extra_slots);
  790. end;
  791. procedure thlcgjvm.a_load_reg_ref(list: TAsmList; fromsize, tosize: tdef; register: tregister; const ref: treference);
  792. var
  793. extra_slots: longint;
  794. begin
  795. extra_slots:=prepare_stack_for_ref(list,ref,false);
  796. a_load_reg_stack(list,fromsize,register);
  797. a_load_stack_ref(list,tosize,ref,extra_slots);
  798. end;
  799. procedure thlcgjvm.a_load_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister);
  800. begin
  801. a_load_reg_stack(list,fromsize,reg1);
  802. if def2regtyp(fromsize)=R_INTREGISTER then
  803. resize_stack_int_val(list,def_cgsize(fromsize),def_cgsize(tosize),false);
  804. a_load_stack_reg(list,tosize,reg2);
  805. end;
  806. procedure thlcgjvm.a_load_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; register: tregister);
  807. var
  808. extra_slots: longint;
  809. begin
  810. extra_slots:=prepare_stack_for_ref(list,ref,false);
  811. a_load_ref_stack(list,fromsize,ref,extra_slots);
  812. if def2regtyp(fromsize)=R_INTREGISTER then
  813. resize_stack_int_val(list,def_cgsize(fromsize),def_cgsize(tosize),false);
  814. a_load_stack_reg(list,tosize,register);
  815. end;
  816. procedure thlcgjvm.a_load_ref_ref(list: TAsmList; fromsize, tosize: tdef; const sref: treference; const dref: treference);
  817. var
  818. extra_sslots,
  819. extra_dslots: longint;
  820. begin
  821. { make sure the destination reference is on top, since in the end the
  822. order has to be "destref, value" -> first create "destref, sourceref" }
  823. extra_dslots:=prepare_stack_for_ref(list,dref,false);
  824. extra_sslots:=prepare_stack_for_ref(list,sref,false);
  825. a_load_ref_stack(list,fromsize,sref,extra_sslots);
  826. if def2regtyp(fromsize)=R_INTREGISTER then
  827. resize_stack_int_val(list,def_cgsize(fromsize),def_cgsize(tosize),dref.arrayreftype<>art_none);
  828. a_load_stack_ref(list,tosize,dref,extra_dslots);
  829. end;
  830. procedure thlcgjvm.a_loadaddr_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; r: tregister);
  831. begin
  832. { only allowed for types that are not implicit pointers in Pascal (in
  833. that case, ref contains a pointer to the actual data and we simply
  834. return that pointer) }
  835. if not jvmimplicitpointertype(fromsize) then
  836. internalerror(2010120534);
  837. a_load_ref_reg(list,java_jlobject,java_jlobject,ref,r);
  838. end;
  839. procedure thlcgjvm.a_op_const_reg(list: TAsmList; Op: TOpCG; size: tdef; a: Aint; reg: TRegister);
  840. begin
  841. a_op_const_reg_reg(list,op,size,a,reg,reg);
  842. end;
  843. procedure thlcgjvm.a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tdef; a: aint; src, dst: tregister);
  844. begin
  845. a_load_reg_stack(list,size,src);
  846. a_op_const_stack(list,op,size,a);
  847. a_load_stack_reg(list,size,dst);
  848. end;
  849. procedure thlcgjvm.a_op_const_ref(list: TAsmList; Op: TOpCG; size: tdef; a: Aint; const ref: TReference);
  850. var
  851. extra_slots: longint;
  852. begin
  853. extra_slots:=prepare_stack_for_ref(list,ref,true);
  854. { TODO, here or in peepholeopt: use iinc when possible }
  855. a_load_ref_stack(list,size,ref,extra_slots);
  856. a_op_const_stack(list,op,size,a);
  857. a_load_stack_ref(list,size,ref,extra_slots);
  858. end;
  859. procedure thlcgjvm.a_op_ref_reg(list: TAsmList; Op: TOpCG; size: tdef; const ref: TReference; reg: TRegister);
  860. begin
  861. a_load_reg_stack(list,size,reg);
  862. a_op_ref_stack(list,op,size,ref);
  863. a_load_stack_reg(list,size,reg);
  864. end;
  865. procedure thlcgjvm.a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tdef; src1, src2, dst: tregister);
  866. begin
  867. a_load_reg_stack(list,size,src2);
  868. a_op_reg_stack(list,op,size,src1);
  869. a_load_stack_reg(list,size,dst);
  870. end;
  871. procedure thlcgjvm.a_op_reg_reg(list: TAsmList; Op: TOpCG; size: tdef; reg1, reg2: TRegister);
  872. begin
  873. a_op_reg_reg_reg(list,op,size,reg1,reg2,reg2);
  874. end;
  875. procedure thlcgjvm.a_cmp_const_ref_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: aint; const ref: treference; l: tasmlabel);
  876. begin
  877. if ref.base<>NR_EVAL_STACK_BASE then
  878. a_load_ref_stack(list,size,ref,prepare_stack_for_ref(list,ref,false));
  879. maybe_adjust_cmp_stackval(list,size,cmp_op);
  880. a_load_const_stack(list,size,maybe_adjust_cmp_constval(size,cmp_op,a),def2regtyp(size));
  881. a_cmp_stack_label(list,size,cmp_op,l);
  882. end;
  883. procedure thlcgjvm.a_cmp_const_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: aint; reg: tregister; l: tasmlabel);
  884. begin
  885. a_load_reg_stack(list,size,reg);
  886. maybe_adjust_cmp_stackval(list,size,cmp_op);
  887. a_load_const_stack(list,size,maybe_adjust_cmp_constval(size,cmp_op,a),def2regtyp(size));
  888. a_cmp_stack_label(list,size,cmp_op,l);
  889. end;
  890. procedure thlcgjvm.a_cmp_ref_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; const ref: treference; reg: tregister; l: tasmlabel);
  891. begin
  892. a_load_reg_stack(list,size,reg);
  893. maybe_adjust_cmp_stackval(list,size,cmp_op);
  894. if ref.base<>NR_EVAL_STACK_BASE then
  895. a_load_ref_stack(list,size,ref,prepare_stack_for_ref(list,ref,false))
  896. else
  897. list.concat(taicpu.op_none(a_swap));
  898. maybe_adjust_cmp_stackval(list,size,cmp_op);
  899. a_cmp_stack_label(list,size,cmp_op,l);
  900. end;
  901. procedure thlcgjvm.a_cmp_reg_ref_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg: tregister; const ref: treference; l: tasmlabel);
  902. begin
  903. if ref.base<>NR_EVAL_STACK_BASE then
  904. a_load_ref_stack(list,size,ref,prepare_stack_for_ref(list,ref,false));
  905. maybe_adjust_cmp_stackval(list,size,cmp_op);
  906. a_load_reg_stack(list,size,reg);
  907. maybe_adjust_cmp_stackval(list,size,cmp_op);
  908. a_cmp_stack_label(list,size,cmp_op,l);
  909. end;
  910. procedure thlcgjvm.a_cmp_reg_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);
  911. begin
  912. a_load_reg_stack(list,size,reg2);
  913. maybe_adjust_cmp_stackval(list,size,cmp_op);
  914. a_load_reg_stack(list,size,reg1);
  915. maybe_adjust_cmp_stackval(list,size,cmp_op);
  916. a_cmp_stack_label(list,size,cmp_op,l);
  917. end;
  918. procedure thlcgjvm.a_jmp_always(list: TAsmList; l: tasmlabel);
  919. begin
  920. list.concat(taicpu.op_sym(a_goto,current_asmdata.RefAsmSymbol(l.name)));
  921. end;
  922. procedure thlcgjvm.concatcopy_normal_array(list: TAsmList; size: tdef; const source, dest: treference);
  923. var
  924. procname: string;
  925. eledef: tdef;
  926. pd: tprocdef;
  927. srsym: tsym;
  928. ndim: longint;
  929. begin
  930. { load copy helper parameters on the stack }
  931. a_load_ref_stack(list,java_jlobject,source,prepare_stack_for_ref(list,source,false));
  932. a_load_ref_stack(list,java_jlobject,dest,prepare_stack_for_ref(list,dest,false));
  933. { call copy helper }
  934. eledef:=tarraydef(size).elementdef;
  935. ndim:=1;
  936. case eledef.typ of
  937. orddef:
  938. begin
  939. case torddef(eledef).ordtype of
  940. pasbool8,s8bit,u8bit,bool8bit,uchar:
  941. procname:='FPC_COPY_JBYTE_ARRAY';
  942. s16bit,u16bit,bool16bit,pasbool16:
  943. procname:='FPC_COPY_JSHORT_ARRAY';
  944. uwidechar:
  945. procname:='FPC_COPY_JCHAR_ARRAY';
  946. s32bit,u32bit,bool32bit,pasbool32:
  947. procname:='FPC_COPY_JINT_ARRAY';
  948. s64bit,u64bit,bool64bit,pasbool64,scurrency:
  949. procname:='FPC_COPY_JLONG_ARRAY';
  950. else
  951. internalerror(2011020504);
  952. end;
  953. end;
  954. floatdef:
  955. case tfloatdef(eledef).floattype of
  956. s32real:
  957. procname:='FPC_COPY_JFLOAT_ARRAY';
  958. s64real:
  959. procname:='FPC_COPY_JDOUBLE_ARRAY';
  960. end;
  961. arraydef:
  962. begin
  963. { call fpc_setlength_dynarr_multidim with deepcopy=true, and extra
  964. parameters }
  965. while (eledef.typ=arraydef) and
  966. not is_dynamic_array(eledef) do
  967. begin
  968. eledef:=tarraydef(eledef).elementdef;
  969. inc(ndim)
  970. end;
  971. if (ndim=1) then
  972. procname:='FPC_COPY_JOBJECT_ARRAY'
  973. else
  974. begin
  975. { deepcopy=true }
  976. a_load_const_stack(list,pasbool8type,1,R_INTREGISTER);
  977. { ndim }
  978. a_load_const_stack(list,s32inttype,ndim,R_INTREGISTER);
  979. { eletype }
  980. a_load_const_stack(list,cwidechartype,ord(jvmarrtype_setlength(eledef)),R_INTREGISTER);
  981. procname:='FPC_SETLENGTH_DYNARR_MULTIDIM';
  982. end;
  983. end;
  984. setdef,
  985. recorddef,
  986. stringdef,
  987. variantdef:
  988. begin
  989. { todo: make a (recursive for records) deep copy, not sure yet how... }
  990. internalerror(2011020505);
  991. end;
  992. else
  993. procname:='FPC_COPY_JOBJECT_ARRAY';
  994. end;
  995. srsym:=tsym(systemunit.find(procname));
  996. if not assigned(srsym) or
  997. (srsym.typ<>procsym) then
  998. Message1(cg_f_unknown_compilerproc,procname);
  999. pd:=tprocdef(tprocsym(srsym).procdeflist[0]);
  1000. a_call_name(list,pd,pd.mangledname,false);
  1001. if ndim=1 then
  1002. decstack(list,2)
  1003. else
  1004. begin
  1005. decstack(list,4);
  1006. { pop return value, must be the same as dest }
  1007. list.concat(taicpu.op_none(a_pop));
  1008. decstack(list,1);
  1009. end;
  1010. end;
  1011. procedure thlcgjvm.g_concatcopy(list: TAsmList; size: tdef; const source, dest: treference);
  1012. var
  1013. handled: boolean;
  1014. begin
  1015. handled:=false;
  1016. case size.typ of
  1017. arraydef:
  1018. begin
  1019. if not is_dynamic_array(size) then
  1020. begin
  1021. concatcopy_normal_array(list,size,source,dest);
  1022. handled:=true;
  1023. end;
  1024. end;
  1025. end;
  1026. if not handled then
  1027. inherited;
  1028. end;
  1029. procedure thlcgjvm.a_loadfpu_ref_ref(list: TAsmList; fromsize, tosize: tdef; const ref1, ref2: treference);
  1030. var
  1031. dstack_slots: longint;
  1032. begin
  1033. dstack_slots:=prepare_stack_for_ref(list,ref2,false);
  1034. a_load_ref_stack(list,fromsize,ref1,prepare_stack_for_ref(list,ref1,false));
  1035. resizestackfpuval(list,def_cgsize(fromsize),def_cgsize(tosize));
  1036. a_load_stack_ref(list,tosize,ref2,dstack_slots);
  1037. end;
  1038. procedure thlcgjvm.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister);
  1039. begin
  1040. a_load_ref_stack(list,fromsize,ref,prepare_stack_for_ref(list,ref,false));
  1041. resizestackfpuval(list,def_cgsize(fromsize),def_cgsize(tosize));
  1042. a_load_stack_reg(list,tosize,reg);
  1043. end;
  1044. procedure thlcgjvm.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tdef; reg: tregister; const ref: treference);
  1045. var
  1046. dstack_slots: longint;
  1047. begin
  1048. dstack_slots:=prepare_stack_for_ref(list,ref,false);
  1049. a_load_reg_stack(list,fromsize,reg);
  1050. resizestackfpuval(list,def_cgsize(fromsize),def_cgsize(tosize));
  1051. a_load_stack_ref(list,tosize,ref,dstack_slots);
  1052. end;
  1053. procedure thlcgjvm.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister);
  1054. begin
  1055. a_load_reg_stack(list,fromsize,reg1);
  1056. resizestackfpuval(list,def_cgsize(fromsize),def_cgsize(tosize));
  1057. a_load_stack_reg(list,tosize,reg2);
  1058. end;
  1059. procedure thlcgjvm.g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean);
  1060. begin
  1061. { the localsize is based on tg.lasttemp -> already in terms of stack
  1062. slots rather than bytes }
  1063. list.concat(tai_directive.Create(asd_jlimit,'locals '+tostr(localsize)));
  1064. list.concat(tai_directive.Create(asd_jlimit,'stack '+tostr(fmaxevalstackheight)));
  1065. end;
  1066. procedure thlcgjvm.g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean);
  1067. var
  1068. retdef: tdef;
  1069. opc: tasmop;
  1070. begin
  1071. if current_procinfo.procdef.proctypeoption=potype_constructor then
  1072. retdef:=voidtype
  1073. else
  1074. retdef:=current_procinfo.procdef.returndef;
  1075. case retdef.typ of
  1076. orddef:
  1077. case torddef(retdef).ordtype of
  1078. uvoid:
  1079. opc:=a_return;
  1080. s64bit,
  1081. u64bit,
  1082. scurrency:
  1083. opc:=a_lreturn;
  1084. else
  1085. opc:=a_ireturn;
  1086. end;
  1087. floatdef:
  1088. case tfloatdef(retdef).floattype of
  1089. s32real:
  1090. opc:=a_freturn;
  1091. s64real:
  1092. opc:=a_dreturn;
  1093. else
  1094. internalerror(2011010213);
  1095. end;
  1096. else
  1097. opc:=a_areturn;
  1098. end;
  1099. list.concat(taicpu.op_none(opc));
  1100. end;
  1101. procedure thlcgjvm.gen_load_return_value(list: TAsmList);
  1102. begin
  1103. { constructors don't return anything in the jvm }
  1104. if current_procinfo.procdef.proctypeoption=potype_constructor then
  1105. exit;
  1106. inherited gen_load_return_value(list);
  1107. end;
  1108. procedure thlcgjvm.record_generated_code_for_procdef(pd: tprocdef; code, data: TAsmList);
  1109. begin
  1110. { add something to the al_procedures list as well, because if all al_*
  1111. lists are empty, the assembler writer isn't called }
  1112. if not code.empty and
  1113. current_asmdata.asmlists[al_procedures].empty then
  1114. current_asmdata.asmlists[al_procedures].concat(tai_align.Create(4));
  1115. pd.exprasmlist:=TAsmList.create;
  1116. pd.exprasmlist.concatlist(code);
  1117. if assigned(data) and
  1118. not data.empty then
  1119. internalerror(2010122801);
  1120. end;
  1121. procedure thlcgjvm.g_incrrefcount(list: TAsmList; t: tdef; const ref: treference);
  1122. begin
  1123. // do nothing
  1124. end;
  1125. procedure thlcgjvm.g_decrrefcount(list: TAsmList; t: tdef; const ref: treference);
  1126. begin
  1127. // do nothing
  1128. end;
  1129. procedure thlcgjvm.g_initialize(list: TAsmList; t: tdef; const ref: treference);
  1130. begin
  1131. a_load_const_ref(list,t,0,ref);
  1132. end;
  1133. procedure thlcgjvm.g_finalize(list: TAsmList; t: tdef; const ref: treference);
  1134. begin
  1135. // do nothing
  1136. end;
  1137. procedure thlcgjvm.location_get_data_ref(list: TAsmList; def: tdef; const l: tlocation; var ref: treference; loadref: boolean; alignment: longint);
  1138. var
  1139. tmploc: tlocation;
  1140. begin
  1141. { This routine is a combination of a generalised a_loadaddr_ref_reg()
  1142. that also works for addresses in registers (in case loadref is false)
  1143. and of a_load_ref_reg (in case loadref is true). It is used for
  1144. a) getting the address of managed types
  1145. b) getting to the actual data of value types that are passed by
  1146. reference by the compiler (and then get a local copy at the caller
  1147. side). Normally, depending on whether this reference is passed in a
  1148. register or reference, we either need a reference with that register
  1149. as base or load the address in that reference and use that as a new
  1150. base.
  1151. Since the JVM cannot take the address of anything, all
  1152. "pass-by-reference" value parameters (which are always aggregate types)
  1153. are already simply the implicit pointer to the data (since arrays,
  1154. records, etc are already internally implicit pointers). This means
  1155. that if "loadref" is true, we must simply return this implicit pointer.
  1156. If it is false, we are supposed the take the address of this implicit
  1157. pointer, which is not possible.
  1158. However, managed types are also implicit pointers in Pascal, so in that
  1159. case "taking the address" again consists of simply returning the
  1160. implicit pointer/current value.
  1161. }
  1162. if not loadref then
  1163. begin
  1164. if not is_managed_type(def) then
  1165. internalerror(2011020601);
  1166. end
  1167. else
  1168. begin
  1169. if not jvmimplicitpointertype(def) then
  1170. internalerror(2011020602);
  1171. end;
  1172. case l.loc of
  1173. LOC_REGISTER,
  1174. LOC_CREGISTER :
  1175. begin
  1176. { the implicit pointer is in a register and has to be in a
  1177. reference -> create a reference and put it there }
  1178. tmploc:=l;
  1179. location_force_mem(list,tmploc,java_jlobject);
  1180. ref:=tmploc.reference;
  1181. end;
  1182. LOC_REFERENCE,
  1183. LOC_CREFERENCE :
  1184. begin
  1185. ref:=l.reference;
  1186. end;
  1187. else
  1188. internalerror(2011020603);
  1189. end;
  1190. end;
  1191. procedure thlcgjvm.g_copyvaluepara_openarray(list: TAsmList; const ref: treference; const lenloc: tlocation; arrdef: tarraydef; destreg: tregister);
  1192. var
  1193. localref: treference;
  1194. arrloc: tlocation;
  1195. stackslots: longint;
  1196. begin
  1197. { temporary reference for passing to concatcopy }
  1198. tg.gethltemp(list,java_jlobject,java_jlobject.size,tt_persistent,localref);
  1199. stackslots:=prepare_stack_for_ref(list,localref,false);
  1200. { create the local copy of the array (lenloc is invalid, get length
  1201. directly from the array) }
  1202. location_reset_ref(arrloc,LOC_REFERENCE,OS_ADDR,sizeof(pint));
  1203. arrloc.reference:=ref;
  1204. g_getarraylen(list,arrloc);
  1205. g_newarray(list,arrdef,1);
  1206. a_load_stack_ref(list,java_jlobject,localref,stackslots);
  1207. { copy the source array to the destination }
  1208. g_concatcopy(list,arrdef,ref,localref);
  1209. { and put the array pointer in the register as expected by the caller }
  1210. a_load_ref_reg(list,java_jlobject,java_jlobject,localref,destreg);
  1211. end;
  1212. procedure thlcgjvm.g_releasevaluepara_openarray(list: TAsmList; arrdef: tarraydef; const l: tlocation);
  1213. begin
  1214. // do nothing, long live garbage collection!
  1215. end;
  1216. procedure thlcgjvm.a_load_stack_reg(list: TAsmList; size: tdef; reg: tregister);
  1217. var
  1218. opc: tasmop;
  1219. finishandval: aint;
  1220. begin
  1221. opc:=loadstoreopc(size,false,false,finishandval);
  1222. list.concat(taicpu.op_reg(opc,reg));
  1223. { avoid problems with getting the size of an open array etc }
  1224. if jvmimplicitpointertype(size) then
  1225. size:=java_jlobject;
  1226. decstack(list,1+ord(size.size>4));
  1227. end;
  1228. procedure thlcgjvm.a_load_stack_ref(list: TAsmList; size: tdef; const ref: treference; extra_slots: longint);
  1229. var
  1230. opc: tasmop;
  1231. finishandval: aint;
  1232. begin
  1233. { fake location that indicates the value has to remain on the stack }
  1234. if ref.base=NR_EVAL_STACK_BASE then
  1235. exit;
  1236. opc:=loadstoreopcref(size,false,ref,finishandval);
  1237. if ref.arrayreftype=art_none then
  1238. list.concat(taicpu.op_ref(opc,ref))
  1239. else
  1240. list.concat(taicpu.op_none(opc));
  1241. { avoid problems with getting the size of an open array etc }
  1242. if jvmimplicitpointertype(size) then
  1243. size:=java_jlobject;
  1244. decstack(list,1+ord(size.size>4)+extra_slots);
  1245. end;
  1246. procedure thlcgjvm.a_load_reg_stack(list: TAsmList; size: tdef; reg: tregister);
  1247. var
  1248. opc: tasmop;
  1249. finishandval: aint;
  1250. begin
  1251. opc:=loadstoreopc(size,true,false,finishandval);
  1252. list.concat(taicpu.op_reg(opc,reg));
  1253. if finishandval<>-1 then
  1254. a_op_const_stack(list,OP_AND,size,finishandval);
  1255. { avoid problems with getting the size of an open array etc }
  1256. if jvmimplicitpointertype(size) then
  1257. size:=java_jlobject;
  1258. incstack(list,1+ord(size.size>4));
  1259. end;
  1260. procedure thlcgjvm.a_load_ref_stack(list: TAsmList; size: tdef; const ref: treference; extra_slots: longint);
  1261. var
  1262. opc: tasmop;
  1263. finishandval: aint;
  1264. begin
  1265. { fake location that indicates the value is already on the stack? }
  1266. if (ref.base=NR_EVAL_STACK_BASE) then
  1267. exit;
  1268. opc:=loadstoreopcref(size,true,ref,finishandval);
  1269. if ref.arrayreftype=art_none then
  1270. list.concat(taicpu.op_ref(opc,ref))
  1271. else
  1272. list.concat(taicpu.op_none(opc));
  1273. if finishandval<>-1 then
  1274. a_op_const_stack(list,OP_AND,size,finishandval);
  1275. { avoid problems with getting the size of an open array etc }
  1276. if jvmimplicitpointertype(size) then
  1277. size:=java_jlobject;
  1278. incstack(list,1+ord(size.size>4)-extra_slots);
  1279. end;
  1280. function thlcgjvm.loadstoreopcref(def: tdef; isload: boolean; const ref: treference; out finishandval: aint): tasmop;
  1281. const
  1282. { isload static }
  1283. getputopc: array[boolean,boolean] of tasmop =
  1284. ((a_putfield,a_putstatic),
  1285. (a_getfield,a_getstatic));
  1286. begin
  1287. if assigned(ref.symbol) then
  1288. begin
  1289. finishandval:=-1;
  1290. { -> either a global (static) field, or a regular field. If a regular
  1291. field, then ref.base contains the self pointer, otherwise
  1292. ref.base=NR_NO. In both cases, the symbol contains all other
  1293. information (combined field name and type descriptor) }
  1294. result:=getputopc[isload,ref.base=NR_NO];
  1295. end
  1296. else
  1297. result:=loadstoreopc(def,isload,ref.arrayreftype<>art_none,finishandval);
  1298. end;
  1299. function thlcgjvm.loadstoreopc(def: tdef; isload, isarray: boolean; out finishandval: aint): tasmop;
  1300. var
  1301. size: longint;
  1302. begin
  1303. finishandval:=-1;
  1304. case def2regtyp(def) of
  1305. R_INTREGISTER:
  1306. begin
  1307. size:=def.size;
  1308. if not isarray then
  1309. begin
  1310. case size of
  1311. 1,2,3,4:
  1312. if isload then
  1313. result:=a_iload
  1314. else
  1315. result:=a_istore;
  1316. 8:
  1317. if isload then
  1318. result:=a_lload
  1319. else
  1320. result:=a_lstore;
  1321. end;
  1322. end
  1323. { array }
  1324. else if isload then
  1325. begin
  1326. case size of
  1327. 1:
  1328. begin
  1329. result:=a_baload;
  1330. if not is_signed(def) then
  1331. finishandval:=255;
  1332. end;
  1333. 2:
  1334. begin
  1335. if is_widechar(def) then
  1336. result:=a_caload
  1337. else
  1338. begin
  1339. result:=a_saload;
  1340. { if we'd treat arrays of word as "array of widechar" we
  1341. could use a_caload, but that would make for even more
  1342. awkward interfacing with external Java code }
  1343. if not is_signed(def) then
  1344. finishandval:=65535;
  1345. end;
  1346. end;
  1347. 4: result:=a_iaload;
  1348. 8: result:=a_laload;
  1349. else
  1350. internalerror(2010120503);
  1351. end
  1352. end
  1353. else
  1354. begin
  1355. case size of
  1356. 1: result:=a_bastore;
  1357. 2: if not is_widechar(def) then
  1358. result:=a_sastore
  1359. else
  1360. result:=a_castore;
  1361. 4: result:=a_iastore;
  1362. 8: result:=a_lastore;
  1363. else
  1364. internalerror(2010120508);
  1365. end
  1366. end
  1367. end;
  1368. R_ADDRESSREGISTER:
  1369. if not isarray then
  1370. if isload then
  1371. result:=a_aload
  1372. else
  1373. result:=a_astore
  1374. else if isload then
  1375. result:=a_aaload
  1376. else
  1377. result:=a_aastore;
  1378. R_FPUREGISTER:
  1379. begin
  1380. case tfloatdef(def).floattype of
  1381. s32real:
  1382. if not isarray then
  1383. if isload then
  1384. result:=a_fload
  1385. else
  1386. result:=a_fstore
  1387. else if isload then
  1388. result:=a_faload
  1389. else
  1390. result:=a_fastore;
  1391. s64real:
  1392. if not isarray then
  1393. if isload then
  1394. result:=a_dload
  1395. else
  1396. result:=a_dstore
  1397. else if isload then
  1398. result:=a_daload
  1399. else
  1400. result:=a_dastore;
  1401. else
  1402. internalerror(2010120504);
  1403. end
  1404. end
  1405. else
  1406. internalerror(2010120502);
  1407. end;
  1408. end;
  1409. procedure thlcgjvm.resize_stack_int_val(list: TAsmList; fromsize, tosize: tcgsize; forarraystore: boolean);
  1410. begin
  1411. if fromsize in [OS_S64,OS_64] then
  1412. begin
  1413. if not(tosize in [OS_S64,OS_64]) then
  1414. begin
  1415. { truncate }
  1416. list.concat(taicpu.op_none(a_l2i));
  1417. decstack(list,1);
  1418. end;
  1419. end
  1420. else if tosize in [OS_S64,OS_64] then
  1421. begin
  1422. { extend }
  1423. list.concat(taicpu.op_none(a_i2l));
  1424. incstack(list,1);
  1425. { if it was an unsigned 32 bit value, remove sign extension }
  1426. if fromsize=OS_32 then
  1427. a_op_const_stack(list,OP_AND,s64inttype,cardinal($ffffffff));
  1428. end;
  1429. { if the value is immediately stored to an array afterwards, the store
  1430. instruction will properly truncate the value; otherwise we may need
  1431. additional truncation, except for 64/32 bit conversions, which are
  1432. already handled above }
  1433. if not forarraystore and
  1434. (not(fromsize in [OS_S64,OS_64,OS_32,OS_S32]) or
  1435. not(tosize in [OS_S64,OS_64,OS_32,OS_S32])) and
  1436. (tcgsize2size[fromsize]>tcgsize2size[tosize]) or
  1437. ((tcgsize2size[fromsize]=tcgsize2size[tosize]) and
  1438. (fromsize<>tosize)) or
  1439. { needs to mask out the sign in the top 16 bits }
  1440. ((fromsize=OS_S8) and
  1441. (tosize=OS_16)) then
  1442. case tosize of
  1443. OS_8:
  1444. a_op_const_stack(list,OP_AND,s32inttype,255);
  1445. OS_S8:
  1446. list.concat(taicpu.op_none(a_i2b));
  1447. OS_16:
  1448. list.concat(taicpu.op_none(a_i2c));
  1449. OS_S16:
  1450. list.concat(taicpu.op_none(a_i2s));
  1451. end;
  1452. end;
  1453. procedure thlcgjvm.resizestackfpuval(list: TAsmList; fromsize, tosize: tcgsize);
  1454. begin
  1455. if (fromsize=OS_F32) and
  1456. (tosize=OS_F64) then
  1457. begin
  1458. list.concat(taicpu.op_none(a_f2d));
  1459. incstack(list,1);
  1460. end
  1461. else if (fromsize=OS_F64) and
  1462. (tosize=OS_F32) then
  1463. begin
  1464. list.concat(taicpu.op_none(a_d2f));
  1465. decstack(list,1);
  1466. end;
  1467. end;
  1468. procedure thlcgjvm.maybepreparedivu32(list: TAsmList; var op: topcg; size: tdef; out isdivu32: boolean);
  1469. begin
  1470. if (op=OP_DIV) and
  1471. (def_cgsize(size)=OS_32) then
  1472. begin
  1473. { needs zero-extension to 64 bit, because the JVM only supports
  1474. signed divisions }
  1475. resize_stack_int_val(list,OS_32,OS_S64,false);
  1476. op:=OP_IDIV;
  1477. isdivu32:=true;
  1478. end
  1479. else
  1480. isdivu32:=false;
  1481. end;
  1482. procedure thlcgjvm.a_call_name_intern(list: TAsmList; pd: tprocdef; const s: string; inheritedcall: boolean);
  1483. var
  1484. opc: tasmop;
  1485. begin
  1486. {
  1487. invoke types:
  1488. * invokeinterface: call method from an interface
  1489. * invokespecial: invoke a constructor, method in a superclass,
  1490. or private instance method
  1491. * invokestatic: invoke a class method (private or not)
  1492. * invokevirtual: invoke a regular method
  1493. }
  1494. case pd.owner.symtabletype of
  1495. globalsymtable,
  1496. staticsymtable,
  1497. localsymtable:
  1498. { regular and nested procedures are turned into static methods }
  1499. opc:=a_invokestatic;
  1500. objectsymtable:
  1501. begin
  1502. case tobjectdef(pd.owner.defowner).objecttype of
  1503. odt_javaclass:
  1504. begin
  1505. if (po_staticmethod in pd.procoptions) then
  1506. opc:=a_invokestatic
  1507. else if (pd.visibility=vis_private) or
  1508. (pd.proctypeoption=potype_constructor) or
  1509. inheritedcall then
  1510. opc:=a_invokespecial
  1511. else
  1512. opc:=a_invokevirtual;
  1513. end;
  1514. odt_interfacejava:
  1515. { static interface methods are not allowed }
  1516. opc:=a_invokeinterface;
  1517. else
  1518. internalerror(2010122601);
  1519. end;
  1520. end;
  1521. else
  1522. internalerror(2010122602);
  1523. end;
  1524. list.concat(taicpu.op_sym(opc,current_asmdata.RefAsmSymbol(s)));
  1525. end;
  1526. procedure create_hlcodegen;
  1527. begin
  1528. hlcg:=thlcgjvm.create;
  1529. create_codegen;
  1530. end;
  1531. end.