hlcgcpu.pas 43 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150
  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(slots: longint);
  35. procedure decstack(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 a_loadfpu_ref_ref(list: TAsmList; fromsize, tosize: tdef; const ref1, ref2: treference); override;
  58. procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister); override;
  59. procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tdef; reg: tregister; const ref: treference); override;
  60. procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister); override;
  61. procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean); override;
  62. procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean); override;
  63. procedure record_generated_code_for_procdef(pd: tprocdef; code, data: TAsmList); override;
  64. { JVM-specific routines }
  65. procedure a_load_stack_reg(list : TAsmList;size: tdef;reg: tregister);
  66. { extra_slots are the slots that are used by the reference, and that
  67. will be removed by the store operation }
  68. procedure a_load_stack_ref(list : TAsmList;size: tdef;const ref: treference;extra_slots: longint);
  69. procedure a_load_reg_stack(list : TAsmList;size: tdef;reg: tregister);
  70. { extra_slots are the slots that are used by the reference, and that
  71. will be removed by the load operation }
  72. procedure a_load_ref_stack(list : TAsmList;size: tdef;const ref: treference;extra_slots: longint);
  73. procedure a_load_const_stack(list : TAsmList;size: tdef;a :aint; typ: TRegisterType);
  74. procedure a_load_loc_stack(list : TAsmList;size: tdef;const loc: tlocation);
  75. procedure a_op_stack(list : TAsmList;op: topcg; size: tdef; trunc32: boolean);
  76. procedure a_op_const_stack(list : TAsmList;op: topcg; size: tdef;a : aint);
  77. procedure a_op_reg_stack(list : TAsmList;op: topcg; size: tdef;reg: tregister);
  78. procedure a_op_ref_stack(list : TAsmList;op: topcg; size: tdef;const ref: treference);
  79. procedure a_op_loc_stack(list : TAsmList;op: topcg; size: tdef;const loc: tlocation);
  80. { this routine expects that all values are already massaged into the
  81. required form (sign bits xor'ed for gt/lt comparisons for OS_32/OS_64,
  82. see http://stackoverflow.com/questions/4068973/c-performing-signed-comparison-in-unsigned-variables-without-casting ) }
  83. procedure a_cmp_stack_label(list : TAsmlist; size: tdef; cmp_op: topcmp; lab: tasmlabel);
  84. { these 2 routines perform the massaging expected by the previous one }
  85. procedure maybe_adjust_cmp_stackval(list : TAsmlist; size: tdef; cmp_op: topcmp);
  86. function maybe_adjust_cmp_constval(size: tdef; cmp_op: topcmp; a: aint): aint;
  87. { truncate/sign extend after performing operations on values < 32 bit
  88. that may have overflowed outside the range }
  89. procedure maybe_adjust_op_result(list: TAsmList; op: TOpCg; size: tdef);
  90. { performs sign/zero extension as required }
  91. procedure resize_stack_int_val(list: TAsmList;fromsize,tosize: tcgsize; forarraystore: boolean);
  92. property maxevalstackheight: longint read fmaxevalstackheight;
  93. protected
  94. procedure gen_load_uninitialized_function_result(list: TAsmList; pd: tprocdef; resdef: tdef; const resloc: tcgpara); override;
  95. { in case of an array, the array base address and index have to be
  96. put on the evaluation stack before the stored value; similarly, for
  97. fields the self pointer has to be loaded first. Also checks whether
  98. the reference is valid. If dup is true, the necessary values are stored
  99. twice. Returns how many stack slots have been consumed, disregarding
  100. the "dup". }
  101. function prepare_stack_for_ref(list: TAsmList; const ref: treference; dup: boolean): longint;
  102. { return the load/store opcode to load/store from/to ref; if the result
  103. has to be and'ed after a load to get the final value, that constant
  104. is returned in finishandval (otherwise that value is set to -1) }
  105. function loadstoreopcref(def: tdef; isload: boolean; const ref: treference; out finishandval: aint): tasmop;
  106. { return the load/store opcode to load/store from/to reg; if the result
  107. has to be and'ed after a load to get the final value, that constant
  108. is returned in finishandval (otherwise that value is set to -1) }
  109. function loadstoreopc(def: tdef; isload, isarray: boolean; out finishandval: aint): tasmop;
  110. procedure resizestackfpuval(list: TAsmList; fromsize, tosize: tcgsize);
  111. { in case of an OS_32 OP_DIV, we have to use an OS_S64 OP_IDIV because the
  112. JVM does not support unsigned divisions }
  113. procedure maybepreparedivu32(list: TAsmList; var op: topcg; size: tdef; out isdivu32: boolean);
  114. { common implementation of a_call_* }
  115. procedure a_call_name_intern(list : TAsmList;pd : tprocdef;const s : string; inheritedcall: boolean);
  116. end;
  117. procedure create_hlcodegen;
  118. const
  119. opcmp2if: array[topcmp] of tasmop = (A_None,
  120. a_ifeq,a_ifgt,a_if_icmplt,a_ifge,a_ifle,
  121. a_ifne,a_ifle,a_iflt,a_ifge,a_ifgt);
  122. implementation
  123. uses
  124. verbose,cutils,
  125. defutil,
  126. aasmtai,aasmcpu,
  127. symconst,
  128. procinfo,cgcpu;
  129. const
  130. TOpCG2IAsmOp : array[topcg] of TAsmOp=( { not = xor -1 }
  131. 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
  132. );
  133. TOpCG2LAsmOp : array[topcg] of TAsmOp=( { not = xor -1 }
  134. 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
  135. );
  136. constructor thlcgjvm.create;
  137. begin
  138. fevalstackheight:=0;
  139. fmaxevalstackheight:=0;
  140. end;
  141. procedure thlcgjvm.incstack(slots: longint);
  142. begin
  143. inc(fevalstackheight,slots);
  144. if (fevalstackheight>fmaxevalstackheight) then
  145. fmaxevalstackheight:=fevalstackheight;
  146. end;
  147. procedure thlcgjvm.decstack(slots: longint);
  148. begin
  149. dec(fevalstackheight,slots);
  150. if (fevalstackheight<0) then
  151. internalerror(2010120501);
  152. end;
  153. procedure thlcgjvm.a_call_name(list: TAsmList; pd: tprocdef; const s: string; weak: boolean);
  154. begin
  155. a_call_name_intern(list,pd,s,false);
  156. end;
  157. procedure thlcgjvm.a_call_name_inherited(list: TAsmList; pd: tprocdef; const s: string);
  158. begin
  159. a_call_name_intern(list,pd,s,true);
  160. end;
  161. procedure thlcgjvm.a_load_const_stack(list : TAsmList;size : tdef;a : aint; typ: TRegisterType);
  162. const
  163. int2opc: array[-1..5] of tasmop = (a_iconst_m1,a_iconst_0,a_iconst_1,
  164. a_iconst_2,a_iconst_3,a_iconst_4,a_iconst_5);
  165. begin
  166. case typ of
  167. R_INTREGISTER:
  168. begin
  169. case def_cgsize(size) of
  170. OS_8,OS_16,OS_32,
  171. OS_S8,OS_S16,OS_S32:
  172. begin
  173. { convert cardinals to longints }
  174. a:=longint(a);
  175. if (a>=-1) and
  176. (a<=5) then
  177. list.concat(taicpu.op_none(int2opc[a]))
  178. else if (a>=low(shortint)) and
  179. (a<=high(shortint)) then
  180. list.concat(taicpu.op_const(a_bipush,a))
  181. else if (a>=low(smallint)) and
  182. (a<=high(smallint)) then
  183. list.concat(taicpu.op_const(a_sipush,a))
  184. else
  185. list.concat(taicpu.op_const(a_ldc,a));
  186. end;
  187. OS_64,OS_S64:
  188. begin
  189. case a of
  190. 0:
  191. list.concat(taicpu.op_none(a_lconst_0));
  192. 1:
  193. list.concat(taicpu.op_none(a_lconst_1));
  194. else
  195. list.concat(taicpu.op_const(a_ldc2_w,a));
  196. end;
  197. incstack(1);
  198. end;
  199. else
  200. internalerror(2010110702);
  201. end;
  202. end;
  203. R_ADDRESSREGISTER:
  204. begin
  205. if a<>0 then
  206. internalerror(2010110701);
  207. list.concat(taicpu.op_none(a_aconst_null));
  208. end;
  209. else
  210. internalerror(2010110703);
  211. end;
  212. incstack(1);
  213. end;
  214. procedure thlcgjvm.a_load_loc_stack(list: TAsmList;size: tdef;const loc: tlocation);
  215. begin
  216. case loc.loc of
  217. LOC_REGISTER,LOC_CREGISTER,
  218. LOC_FPUREGISTER,LOC_CFPUREGISTER:
  219. a_load_reg_stack(list,size,loc.register);
  220. LOC_REFERENCE,LOC_CREFERENCE:
  221. a_load_ref_stack(list,size,loc.reference,prepare_stack_for_ref(list,loc.reference,false));
  222. LOC_CONSTANT:
  223. a_load_const_stack(list,size,loc.value,def2regtyp(size));
  224. else
  225. internalerror(2011010401);
  226. end;
  227. end;
  228. procedure thlcgjvm.a_op_stack(list: TAsmList; op: topcg; size: tdef; trunc32: boolean);
  229. var
  230. cgsize: tcgsize;
  231. begin
  232. if not trunc32 then
  233. cgsize:=def_cgsize(size)
  234. else
  235. begin
  236. resize_stack_int_val(list,OS_32,OS_S64,false);
  237. cgsize:=OS_S64;
  238. end;
  239. case cgsize of
  240. OS_8,OS_S8,
  241. OS_16,OS_S16,
  242. OS_32,OS_S32:
  243. begin
  244. { not = xor 1 for boolean, xor -1 for the rest}
  245. if op=OP_NOT then
  246. begin
  247. if not is_pasbool(size) then
  248. a_load_const_stack(list,s32inttype,high(cardinal),R_INTREGISTER)
  249. else
  250. a_load_const_stack(list,size,1,R_INTREGISTER);
  251. op:=OP_XOR;
  252. end;
  253. if TOpCG2IAsmOp[op]=A_None then
  254. internalerror(2010120532);
  255. list.concat(taicpu.op_none(TOpCG2IAsmOp[op]));
  256. maybe_adjust_op_result(list,op,size);
  257. if op<>OP_NEG then
  258. decstack(1);
  259. end;
  260. OS_64,OS_S64:
  261. begin
  262. { unsigned 64 bit division must be done via a helper }
  263. if op=OP_DIV then
  264. internalerror(2010120530);
  265. { not = xor -1 }
  266. if op=OP_NOT then
  267. begin
  268. a_load_const_stack(list,s64inttype,-1,R_INTREGISTER);
  269. op:=OP_XOR;
  270. end;
  271. if TOpCG2LAsmOp[op]=A_None then
  272. internalerror(2010120533);
  273. list.concat(taicpu.op_none(TOpCG2LAsmOp[op]));
  274. if op<>OP_NEG then
  275. decstack(2);
  276. end;
  277. else
  278. internalerror(2010120531);
  279. end;
  280. if trunc32 then
  281. begin
  282. list.concat(taicpu.op_none(a_l2i));
  283. decstack(1);
  284. end;
  285. end;
  286. procedure thlcgjvm.a_op_const_stack(list: TAsmList;op: topcg;size: tdef;a: aint);
  287. var
  288. trunc32: boolean;
  289. begin
  290. { use "integer to (wide)char" narrowing opcode for "and 65535" }
  291. if (op=OP_AND) and
  292. (def_cgsize(size) in [OS_16,OS_S16,OS_32,OS_S32]) and
  293. (a=65535) then
  294. list.concat(taicpu.op_none(a_i2c))
  295. else
  296. begin
  297. maybepreparedivu32(list,op,size,trunc32);
  298. a_load_const_stack(list,size,a,R_INTREGISTER);
  299. a_op_stack(list,op,size,trunc32);
  300. end;
  301. end;
  302. procedure thlcgjvm.a_op_reg_stack(list: TAsmList; op: topcg; size: tdef; reg: tregister);
  303. var
  304. trunc32: boolean;
  305. begin
  306. maybepreparedivu32(list,op,size,trunc32);
  307. if not(op in [OP_NEG,OP_NOT]) then
  308. a_load_reg_stack(list,size,reg);
  309. a_op_stack(list,op,size,trunc32);
  310. end;
  311. procedure thlcgjvm.a_op_ref_stack(list: TAsmList; op: topcg; size: tdef; const ref: treference);
  312. var
  313. trunc32: boolean;
  314. begin
  315. { ref must not be the stack top, because that may indicate an error
  316. (it means that we will perform an operation of the stack top onto
  317. itself, so that means the two values have been loaded manually prior
  318. to calling this routine, instead of letting this routine load one of
  319. them; if something like that is needed, call a_op_stack() directly) }
  320. if ref.base=NR_EVAL_STACK_BASE then
  321. internalerror(2010121102);
  322. maybepreparedivu32(list,op,size,trunc32);
  323. if not(op in [OP_NEG,OP_NOT]) then
  324. a_load_ref_stack(list,size,ref,prepare_stack_for_ref(list,ref,false));
  325. a_op_stack(list,op,size,trunc32);
  326. end;
  327. procedure thlcgjvm.a_op_loc_stack(list: TAsmList; op: topcg; size: tdef; const loc: tlocation);
  328. begin
  329. case loc.loc of
  330. LOC_REGISTER,LOC_CREGISTER:
  331. a_op_reg_stack(list,op,size,loc.register);
  332. LOC_REFERENCE,LOC_CREFERENCE:
  333. a_op_ref_stack(list,op,size,loc.reference);
  334. LOC_CONSTANT:
  335. a_op_const_stack(list,op,size,loc.value);
  336. else
  337. internalerror(2011011415)
  338. end;
  339. end;
  340. procedure thlcgjvm.a_cmp_stack_label(list: TAsmlist; size: tdef; cmp_op: topcmp; lab: tasmlabel);
  341. const
  342. opcmp2icmp: array[topcmp] of tasmop = (A_None,
  343. a_if_icmpeq,a_if_icmpgt,a_if_icmplt,a_if_icmpge,a_if_icmple,
  344. a_if_icmpne,a_if_icmple,a_if_icmplt,a_if_icmpge,a_if_icmpgt);
  345. var
  346. cgsize: tcgsize;
  347. begin
  348. case def2regtyp(size) of
  349. R_INTREGISTER:
  350. begin
  351. cgsize:=def_cgsize(size);
  352. case cgsize of
  353. OS_S8,OS_8,
  354. OS_16,OS_S16,
  355. OS_S32,OS_32:
  356. begin
  357. list.concat(taicpu.op_sym(opcmp2icmp[cmp_op],lab));
  358. decstack(2);
  359. end;
  360. OS_64,OS_S64:
  361. begin
  362. list.concat(taicpu.op_none(a_lcmp));
  363. decstack(3);
  364. list.concat(taicpu.op_sym(opcmp2if[cmp_op],lab));
  365. decstack(1);
  366. end;
  367. else
  368. internalerror(2010120538);
  369. end;
  370. end;
  371. R_ADDRESSREGISTER:
  372. begin
  373. case cmp_op of
  374. OC_EQ:
  375. list.concat(taicpu.op_sym(a_if_acmpeq,lab));
  376. OC_NE:
  377. list.concat(taicpu.op_sym(a_if_acmpne,lab));
  378. else
  379. internalerror(2010120537);
  380. end;
  381. decstack(2);
  382. end;
  383. else
  384. internalerror(2010120538);
  385. end;
  386. end;
  387. procedure thlcgjvm.maybe_adjust_cmp_stackval(list: TAsmlist; size: tdef; cmp_op: topcmp);
  388. begin
  389. if (cmp_op in [OC_EQ,OC_NE]) or
  390. (def2regtyp(size)<>R_INTREGISTER) then
  391. exit;
  392. { http://stackoverflow.com/questions/4068973/c-performing-signed-comparison-in-unsigned-variables-without-casting }
  393. case def_cgsize(size) of
  394. OS_32:
  395. a_op_const_stack(list,OP_XOR,size,cardinal($80000000));
  396. OS_64:
  397. a_op_const_stack(list,OP_XOR,size,aint($8000000000000000));
  398. end;
  399. end;
  400. function thlcgjvm.maybe_adjust_cmp_constval(size: tdef; cmp_op: topcmp; a: aint): aint;
  401. begin
  402. result:=a;
  403. if (cmp_op in [OC_EQ,OC_NE]) or
  404. (def2regtyp(size)<>R_INTREGISTER) then
  405. exit;
  406. case def_cgsize(size) of
  407. OS_32:
  408. result:=a xor cardinal($80000000);
  409. OS_64:
  410. result:=a xor aint($8000000000000000);
  411. end;
  412. end;
  413. procedure thlcgjvm.maybe_adjust_op_result(list: TAsmList; op: TOpCg; size: tdef);
  414. const
  415. overflowops = [OP_MUL,OP_SHL,OP_ADD,OP_SUB,OP_NOT,OP_NEG];
  416. begin
  417. if (op in overflowops) and
  418. (def_cgsize(size) in [OS_8,OS_S8,OS_16,OS_S16]) then
  419. resize_stack_int_val(list,OS_S32,def_cgsize(size),false);
  420. end;
  421. procedure thlcgjvm.gen_load_uninitialized_function_result(list: TAsmList; pd: tprocdef; resdef: tdef; const resloc: tcgpara);
  422. begin
  423. { constructors don't return anything in Java }
  424. if pd.proctypeoption=potype_constructor then
  425. exit;
  426. { must return a value of the correct type on the evaluation stack }
  427. case def2regtyp(resdef) of
  428. R_INTREGISTER,
  429. R_ADDRESSREGISTER:
  430. a_load_const_cgpara(list,resdef,0,resloc);
  431. R_FPUREGISTER:
  432. case tfloatdef(resdef).floattype of
  433. s32real:
  434. list.concat(taicpu.op_none(a_fconst_0));
  435. s64real:
  436. list.concat(taicpu.op_none(a_dconst_0));
  437. else
  438. internalerror(2011010302);
  439. end
  440. else
  441. internalerror(2011010301);
  442. end;
  443. end;
  444. function thlcgjvm.prepare_stack_for_ref(list: TAsmList; const ref: treference; dup: boolean): longint;
  445. var
  446. href: treference;
  447. begin
  448. result:=0;
  449. { fake location that indicates the value is already on the stack? }
  450. if (ref.base=NR_EVAL_STACK_BASE) then
  451. exit;
  452. if ref.arrayreftype=art_none then
  453. begin
  454. { non-array accesses cannot have an index reg }
  455. if ref.index<>NR_NO then
  456. internalerror(2010120509);
  457. if (ref.base<>NR_NO) then
  458. begin
  459. if (ref.base<>NR_STACK_POINTER_REG) then
  460. begin
  461. { regular field -> load self on the stack }
  462. a_load_reg_stack(list,voidpointertype,ref.base);
  463. if dup then
  464. begin
  465. list.concat(taicpu.op_none(a_dup));
  466. incstack(1);
  467. end;
  468. { field name/type encoded in symbol, no index/offset }
  469. if not assigned(ref.symbol) or
  470. (ref.offset<>0) then
  471. internalerror(2010120524);
  472. result:=1;
  473. end
  474. else
  475. begin
  476. { local variable -> offset encoded in opcode and nothing to
  477. do here, except for checking that it's a valid reference }
  478. if assigned(ref.symbol) then
  479. internalerror(2010120523);
  480. end;
  481. end
  482. else
  483. begin
  484. { static field -> nothing to do here, except for validity check }
  485. if not assigned(ref.symbol) or
  486. (ref.offset<>0) then
  487. internalerror(2010120525);
  488. end;
  489. end
  490. else
  491. begin
  492. { arrays have implicit dereference -> pointer to array must have been
  493. loaded into base reg }
  494. if (ref.base=NR_NO) or
  495. (ref.base=NR_STACK_POINTER_REG) then
  496. internalerror(2010120511);
  497. if assigned(ref.symbol) then
  498. internalerror(2010120512);
  499. { stack: ... -> ..., arrayref, index }
  500. { load array base address }
  501. a_load_reg_stack(list,voidpointertype,ref.base);
  502. { index can either be in a register, or located in a simple memory
  503. location (since we have to load it anyway) }
  504. if ref.arrayreftype=art_indexreg then
  505. begin
  506. if ref.index=NR_NO then
  507. internalerror(2010120513);
  508. { all array indices in Java are 32 bit ints }
  509. a_load_reg_stack(list,s32inttype,ref.index);
  510. end
  511. else
  512. begin
  513. reference_reset_base(href,ref.indexbase,ref.indexoffset,4);
  514. href.symbol:=href.indexsymbol;
  515. a_load_ref_stack(list,s32inttype,href,prepare_stack_for_ref(list,href,false));
  516. end;
  517. { adjustment of the index }
  518. if ref.offset<>0 then
  519. a_op_const_stack(list,OP_ADD,s32inttype,ref.offset);
  520. if dup then
  521. begin
  522. list.concat(taicpu.op_none(a_dup2));
  523. incstack(2);
  524. end;
  525. result:=2;
  526. end;
  527. end;
  528. procedure thlcgjvm.a_load_const_reg(list: TAsmList; tosize: tdef; a: aint; register: tregister);
  529. begin
  530. a_load_const_stack(list,tosize,a,def2regtyp(tosize));
  531. a_load_stack_reg(list,tosize,register);
  532. end;
  533. procedure thlcgjvm.a_load_const_ref(list: TAsmList; tosize: tdef; a: aint; const ref: treference);
  534. var
  535. extra_slots: longint;
  536. begin
  537. extra_slots:=prepare_stack_for_ref(list,ref,false);
  538. a_load_const_stack(list,tosize,a,def2regtyp(tosize));
  539. a_load_stack_ref(list,tosize,ref,extra_slots);
  540. decstack(extra_slots);
  541. end;
  542. procedure thlcgjvm.a_load_reg_ref(list: TAsmList; fromsize, tosize: tdef; register: tregister; const ref: treference);
  543. var
  544. extra_slots: longint;
  545. begin
  546. extra_slots:=prepare_stack_for_ref(list,ref,false);
  547. a_load_reg_stack(list,fromsize,register);
  548. a_load_stack_ref(list,tosize,ref,extra_slots);
  549. decstack(extra_slots);
  550. end;
  551. procedure thlcgjvm.a_load_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister);
  552. begin
  553. a_load_reg_stack(list,fromsize,reg1);
  554. if def2regtyp(fromsize)=R_INTREGISTER then
  555. resize_stack_int_val(list,def_cgsize(fromsize),def_cgsize(tosize),false);
  556. a_load_stack_reg(list,tosize,reg2);
  557. end;
  558. procedure thlcgjvm.a_load_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; register: tregister);
  559. var
  560. extra_slots: longint;
  561. begin
  562. extra_slots:=prepare_stack_for_ref(list,ref,false);
  563. a_load_ref_stack(list,fromsize,ref,extra_slots);
  564. if def2regtyp(fromsize)=R_INTREGISTER then
  565. resize_stack_int_val(list,def_cgsize(fromsize),def_cgsize(tosize),false);
  566. a_load_stack_reg(list,tosize,register);
  567. end;
  568. procedure thlcgjvm.a_load_ref_ref(list: TAsmList; fromsize, tosize: tdef; const sref: treference; const dref: treference);
  569. var
  570. extra_sslots,
  571. extra_dslots: longint;
  572. begin
  573. { make sure the destination reference is on top, since in the end the
  574. order has to be "destref, value" -> first create "destref, sourceref" }
  575. extra_dslots:=prepare_stack_for_ref(list,dref,false);
  576. extra_sslots:=prepare_stack_for_ref(list,sref,false);
  577. a_load_ref_stack(list,fromsize,sref,extra_sslots);
  578. if def2regtyp(fromsize)=R_INTREGISTER then
  579. resize_stack_int_val(list,def_cgsize(fromsize),def_cgsize(tosize),dref.arrayreftype<>art_none);
  580. a_load_stack_ref(list,tosize,dref,extra_dslots);
  581. end;
  582. procedure thlcgjvm.a_loadaddr_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; r: tregister);
  583. begin
  584. internalerror(2010120534);
  585. end;
  586. procedure thlcgjvm.a_op_const_reg(list: TAsmList; Op: TOpCG; size: tdef; a: Aint; reg: TRegister);
  587. begin
  588. a_op_const_reg_reg(list,op,size,a,reg,reg);
  589. end;
  590. procedure thlcgjvm.a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tdef; a: aint; src, dst: tregister);
  591. begin
  592. a_load_reg_stack(list,size,src);
  593. a_op_const_stack(list,op,size,a);
  594. a_load_stack_reg(list,size,dst);
  595. end;
  596. procedure thlcgjvm.a_op_const_ref(list: TAsmList; Op: TOpCG; size: tdef; a: Aint; const ref: TReference);
  597. var
  598. extra_slots: longint;
  599. begin
  600. extra_slots:=prepare_stack_for_ref(list,ref,true);
  601. { TODO, here or in peepholeopt: use iinc when possible }
  602. a_load_ref_stack(list,size,ref,extra_slots);
  603. a_op_const_stack(list,op,size,a);
  604. a_load_stack_ref(list,size,ref,extra_slots);
  605. end;
  606. procedure thlcgjvm.a_op_ref_reg(list: TAsmList; Op: TOpCG; size: tdef; const ref: TReference; reg: TRegister);
  607. begin
  608. a_load_reg_stack(list,size,reg);
  609. a_op_ref_stack(list,op,size,ref);
  610. a_load_stack_reg(list,size,reg);
  611. end;
  612. procedure thlcgjvm.a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tdef; src1, src2, dst: tregister);
  613. begin
  614. a_load_reg_stack(list,size,src2);
  615. a_op_reg_stack(list,op,size,src1);
  616. a_load_stack_reg(list,size,dst);
  617. end;
  618. procedure thlcgjvm.a_op_reg_reg(list: TAsmList; Op: TOpCG; size: tdef; reg1, reg2: TRegister);
  619. begin
  620. a_op_reg_reg_reg(list,op,size,reg1,reg2,reg2);
  621. end;
  622. procedure thlcgjvm.a_cmp_const_ref_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: aint; const ref: treference; l: tasmlabel);
  623. begin
  624. a_load_const_stack(list,size,maybe_adjust_cmp_constval(size,cmp_op,a),R_INTREGISTER);
  625. if ref.base<>NR_EVAL_STACK_BASE then
  626. a_load_ref_stack(list,size,ref,prepare_stack_for_ref(list,ref,false))
  627. else
  628. list.concat(taicpu.op_none(a_swap));
  629. maybe_adjust_cmp_stackval(list,size,cmp_op);
  630. a_cmp_stack_label(list,size,cmp_op,l);
  631. end;
  632. procedure thlcgjvm.a_cmp_const_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: aint; reg: tregister; l: tasmlabel);
  633. begin
  634. a_load_const_stack(list,size,maybe_adjust_cmp_constval(size,cmp_op,a),R_INTREGISTER);
  635. a_load_reg_stack(list,size,reg);
  636. maybe_adjust_cmp_stackval(list,size,cmp_op);
  637. a_cmp_stack_label(list,size,cmp_op,l);
  638. end;
  639. procedure thlcgjvm.a_cmp_ref_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; const ref: treference; reg: tregister; l: tasmlabel);
  640. begin
  641. if ref.base<>NR_EVAL_STACK_BASE then
  642. a_load_ref_stack(list,size,ref,prepare_stack_for_ref(list,ref,false));
  643. maybe_adjust_cmp_stackval(list,size,cmp_op);
  644. a_load_reg_stack(list,size,reg);
  645. maybe_adjust_cmp_stackval(list,size,cmp_op);
  646. a_cmp_stack_label(list,size,cmp_op,l);
  647. end;
  648. procedure thlcgjvm.a_cmp_reg_ref_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg: tregister; const ref: treference; l: tasmlabel);
  649. begin
  650. a_load_reg_stack(list,size,reg);
  651. maybe_adjust_cmp_stackval(list,size,cmp_op);
  652. if ref.base<>NR_EVAL_STACK_BASE then
  653. a_load_ref_stack(list,size,ref,prepare_stack_for_ref(list,ref,false))
  654. else
  655. list.concat(taicpu.op_none(a_swap));
  656. maybe_adjust_cmp_stackval(list,size,cmp_op);
  657. a_cmp_stack_label(list,size,cmp_op,l);
  658. end;
  659. procedure thlcgjvm.a_cmp_reg_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);
  660. begin
  661. a_load_reg_stack(list,size,reg1);
  662. maybe_adjust_cmp_stackval(list,size,cmp_op);
  663. a_load_reg_stack(list,size,reg2);
  664. maybe_adjust_cmp_stackval(list,size,cmp_op);
  665. a_cmp_stack_label(list,size,cmp_op,l);
  666. end;
  667. procedure thlcgjvm.a_jmp_always(list: TAsmList; l: tasmlabel);
  668. begin
  669. list.concat(taicpu.op_sym(a_goto,current_asmdata.RefAsmSymbol(l.name)));
  670. end;
  671. procedure thlcgjvm.a_loadfpu_ref_ref(list: TAsmList; fromsize, tosize: tdef; const ref1, ref2: treference);
  672. var
  673. dstack_slots: longint;
  674. begin
  675. dstack_slots:=prepare_stack_for_ref(list,ref2,false);
  676. a_load_ref_stack(list,fromsize,ref1,prepare_stack_for_ref(list,ref1,false));
  677. resizestackfpuval(list,def_cgsize(fromsize),def_cgsize(tosize));
  678. a_load_stack_ref(list,tosize,ref2,dstack_slots);
  679. end;
  680. procedure thlcgjvm.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister);
  681. begin
  682. a_load_ref_stack(list,fromsize,ref,prepare_stack_for_ref(list,ref,false));
  683. resizestackfpuval(list,def_cgsize(fromsize),def_cgsize(tosize));
  684. a_load_stack_reg(list,tosize,reg);
  685. end;
  686. procedure thlcgjvm.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tdef; reg: tregister; const ref: treference);
  687. var
  688. dstack_slots: longint;
  689. begin
  690. dstack_slots:=prepare_stack_for_ref(list,ref,false);
  691. a_load_reg_stack(list,fromsize,reg);
  692. resizestackfpuval(list,def_cgsize(fromsize),def_cgsize(tosize));
  693. a_load_stack_ref(list,tosize,ref,dstack_slots);
  694. end;
  695. procedure thlcgjvm.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister);
  696. begin
  697. a_load_reg_stack(list,fromsize,reg1);
  698. resizestackfpuval(list,def_cgsize(fromsize),def_cgsize(tosize));
  699. a_load_stack_reg(list,tosize,reg2);
  700. end;
  701. procedure thlcgjvm.g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean);
  702. begin
  703. { the localsize is based on tg.lasttemp -> already in terms of stack
  704. slots rather than bytes }
  705. list.concat(tai_directive.Create(asd_jlimit,'locals '+tostr(localsize)));
  706. list.concat(tai_directive.Create(asd_jlimit,'stack '+tostr(fmaxevalstackheight)));
  707. end;
  708. procedure thlcgjvm.g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean);
  709. var
  710. opc: tasmop;
  711. begin
  712. case current_procinfo.procdef.returndef.typ of
  713. orddef:
  714. case torddef(current_procinfo.procdef.returndef).ordtype of
  715. uvoid:
  716. opc:=a_return;
  717. s64bit,
  718. u64bit,
  719. scurrency:
  720. opc:=a_lreturn;
  721. else
  722. opc:=a_ireturn;
  723. end;
  724. floatdef:
  725. case tfloatdef(current_procinfo.procdef.returndef).floattype of
  726. s32real:
  727. opc:=a_freturn;
  728. s64real:
  729. opc:=a_dreturn;
  730. else
  731. internalerror(2011010213);
  732. end;
  733. else
  734. opc:=a_areturn;
  735. end;
  736. list.concat(taicpu.op_none(opc));
  737. end;
  738. procedure thlcgjvm.record_generated_code_for_procdef(pd: tprocdef; code, data: TAsmList);
  739. begin
  740. { add something to the al_procedures list as well, because if all al_*
  741. lists are empty, the assembler writer isn't called }
  742. if not code.empty and
  743. current_asmdata.asmlists[al_procedures].empty then
  744. current_asmdata.asmlists[al_procedures].concat(tai_align.Create(4));
  745. pd.exprasmlist:=TAsmList.create;
  746. pd.exprasmlist.concatlist(code);
  747. if assigned(data) and
  748. not data.empty then
  749. internalerror(2010122801);
  750. end;
  751. procedure thlcgjvm.a_load_stack_reg(list: TAsmList; size: tdef; reg: tregister);
  752. var
  753. opc: tasmop;
  754. finishandval: aint;
  755. begin
  756. opc:=loadstoreopc(size,false,false,finishandval);
  757. list.concat(taicpu.op_reg(opc,reg));
  758. decstack(1+ord(size.size>4));
  759. end;
  760. procedure thlcgjvm.a_load_stack_ref(list: TAsmList; size: tdef; const ref: treference; extra_slots: longint);
  761. var
  762. opc: tasmop;
  763. finishandval: aint;
  764. begin
  765. { fake location that indicates the value has to remain on the stack }
  766. if ref.base=NR_EVAL_STACK_BASE then
  767. exit;
  768. opc:=loadstoreopcref(size,false,ref,finishandval);
  769. if ref.arrayreftype=art_none then
  770. list.concat(taicpu.op_ref(opc,ref))
  771. else
  772. list.concat(taicpu.op_none(opc));
  773. decstack(1+ord(size.size>4)+extra_slots);
  774. end;
  775. procedure thlcgjvm.a_load_reg_stack(list: TAsmList; size: tdef; reg: tregister);
  776. var
  777. opc: tasmop;
  778. finishandval: aint;
  779. begin
  780. opc:=loadstoreopc(size,true,false,finishandval);
  781. list.concat(taicpu.op_reg(opc,reg));
  782. if finishandval<>-1 then
  783. a_op_const_stack(list,OP_AND,size,finishandval);
  784. incstack(1+ord(size.size>4));
  785. end;
  786. procedure thlcgjvm.a_load_ref_stack(list: TAsmList; size: tdef; const ref: treference; extra_slots: longint);
  787. var
  788. opc: tasmop;
  789. finishandval: aint;
  790. begin
  791. { fake location that indicates the value is already on the stack? }
  792. if (ref.base=NR_EVAL_STACK_BASE) then
  793. exit;
  794. opc:=loadstoreopcref(size,true,ref,finishandval);
  795. if ref.arrayreftype=art_none then
  796. list.concat(taicpu.op_ref(opc,ref))
  797. else
  798. list.concat(taicpu.op_none(opc));
  799. if finishandval<>-1 then
  800. a_op_const_stack(list,OP_AND,size,finishandval);
  801. incstack(1+ord(size.size>4)-extra_slots);
  802. end;
  803. function thlcgjvm.loadstoreopcref(def: tdef; isload: boolean; const ref: treference; out finishandval: aint): tasmop;
  804. const
  805. { isload static }
  806. getputopc: array[boolean,boolean] of tasmop =
  807. ((a_putfield,a_putstatic),
  808. (a_getfield,a_getstatic));
  809. var
  810. size: aint;
  811. begin
  812. if assigned(ref.symbol) then
  813. begin
  814. finishandval:=-1;
  815. { -> either a global (static) field, or a regular field. If a regular
  816. field, then ref.base contains the self pointer, otherwise
  817. ref.base=NR_NO. In both cases, the symbol contains all other
  818. information (combined field name and type descriptor) }
  819. result:=getputopc[isload,ref.base=NR_NO];
  820. end
  821. else
  822. result:=loadstoreopc(def,isload,ref.arrayreftype<>art_none,finishandval);
  823. end;
  824. function thlcgjvm.loadstoreopc(def: tdef; isload, isarray: boolean; out finishandval: aint): tasmop;
  825. var
  826. size: longint;
  827. begin
  828. finishandval:=-1;
  829. case def2regtyp(def) of
  830. R_INTREGISTER:
  831. begin
  832. size:=def.size;
  833. if not isarray then
  834. begin
  835. case size of
  836. 1,2,3,4:
  837. if isload then
  838. result:=a_iload
  839. else
  840. result:=a_istore;
  841. 8:
  842. if isload then
  843. result:=a_lload
  844. else
  845. result:=a_lstore;
  846. end;
  847. end
  848. { array }
  849. else if isload then
  850. begin
  851. case size of
  852. 1:
  853. begin
  854. result:=a_baload;
  855. if not is_signed(def) then
  856. finishandval:=255;
  857. end;
  858. 2:
  859. begin
  860. if is_widechar(def) then
  861. result:=a_caload
  862. else
  863. begin
  864. result:=a_saload;
  865. { if we'd treat arrays of word as "array of widechar" we
  866. could use a_caload, but that would make for even more
  867. awkward interfacing with external Java code }
  868. if not is_signed(def) then
  869. finishandval:=65535;
  870. end;
  871. end;
  872. 4: result:=a_iaload;
  873. 8: result:=a_laload;
  874. else
  875. internalerror(2010120503);
  876. end
  877. end
  878. else
  879. begin
  880. case size of
  881. 1: result:=a_bastore;
  882. 2: if not is_widechar(def) then
  883. result:=a_sastore
  884. else
  885. result:=a_castore;
  886. 4: result:=a_iastore;
  887. 8: result:=a_lastore;
  888. else
  889. internalerror(2010120508);
  890. end
  891. end
  892. end;
  893. R_ADDRESSREGISTER:
  894. if not isarray then
  895. if isload then
  896. result:=a_aload
  897. else
  898. result:=a_astore
  899. else if isload then
  900. result:=a_aaload
  901. else
  902. result:=a_aastore;
  903. R_FPUREGISTER:
  904. begin
  905. case tfloatdef(def).floattype of
  906. s32real:
  907. if not isarray then
  908. if isload then
  909. result:=a_fload
  910. else
  911. result:=a_fstore
  912. else if isload then
  913. result:=a_faload
  914. else
  915. result:=a_fastore;
  916. s64real:
  917. if not isarray then
  918. if isload then
  919. result:=a_dload
  920. else
  921. result:=a_dstore
  922. else if isload then
  923. result:=a_daload
  924. else
  925. result:=a_dastore;
  926. else
  927. internalerror(2010120504);
  928. end
  929. end
  930. else
  931. internalerror(2010120502);
  932. end;
  933. end;
  934. procedure thlcgjvm.resize_stack_int_val(list: TAsmList; fromsize, tosize: tcgsize; forarraystore: boolean);
  935. begin
  936. if fromsize in [OS_S64,OS_64] then
  937. begin
  938. if not(tosize in [OS_S64,OS_64]) then
  939. begin
  940. { truncate }
  941. list.concat(taicpu.op_none(a_l2i));
  942. decstack(1);
  943. end;
  944. end
  945. else if tosize in [OS_S64,OS_64] then
  946. begin
  947. { extend }
  948. list.concat(taicpu.op_none(a_i2l));
  949. incstack(1);
  950. { if it was an unsigned 32 bit value, remove sign extension }
  951. if fromsize=OS_32 then
  952. a_op_const_stack(list,OP_AND,s64inttype,cardinal($ffffffff));
  953. end;
  954. { if the value is immediately stored to an array afterwards, the store
  955. instruction will properly truncate the value; otherwise we may need
  956. additional truncation, except for 64/32 bit conversions, which are
  957. already handled above }
  958. if not forarraystore and
  959. (not(fromsize in [OS_S64,OS_64,OS_32,OS_S32]) or
  960. not(tosize in [OS_S64,OS_64,OS_32,OS_S32])) and
  961. (tcgsize2size[fromsize]>tcgsize2size[tosize]) or
  962. ((tcgsize2size[fromsize]=tcgsize2size[tosize]) and
  963. (fromsize<>tosize)) or
  964. { needs to mask out the sign in the top 16 bits }
  965. ((fromsize=OS_S8) and
  966. (tosize=OS_16)) then
  967. case tosize of
  968. OS_8:
  969. a_op_const_stack(list,OP_AND,s32inttype,255);
  970. OS_S8:
  971. list.concat(taicpu.op_none(a_i2b));
  972. OS_16:
  973. list.concat(taicpu.op_none(a_i2c));
  974. OS_S16:
  975. list.concat(taicpu.op_none(a_i2s));
  976. end;
  977. end;
  978. procedure thlcgjvm.resizestackfpuval(list: TAsmList; fromsize, tosize: tcgsize);
  979. begin
  980. if (fromsize=OS_F32) and
  981. (tosize=OS_F64) then
  982. begin
  983. list.concat(taicpu.op_none(a_f2d));
  984. incstack(1);
  985. end
  986. else if (fromsize=OS_F64) and
  987. (tosize=OS_F32) then
  988. begin
  989. list.concat(taicpu.op_none(a_d2f));
  990. decstack(1);
  991. end;
  992. end;
  993. procedure thlcgjvm.maybepreparedivu32(list: TAsmList; var op: topcg; size: tdef; out isdivu32: boolean);
  994. begin
  995. if (op=OP_DIV) and
  996. (def_cgsize(size)=OS_32) then
  997. begin
  998. { needs zero-extension to 64 bit, because the JVM only supports
  999. signed divisions }
  1000. resize_stack_int_val(list,OS_32,OS_S64,false);
  1001. op:=OP_IDIV;
  1002. isdivu32:=true;
  1003. end
  1004. else
  1005. isdivu32:=false;
  1006. end;
  1007. procedure thlcgjvm.a_call_name_intern(list: TAsmList; pd: tprocdef; const s: string; inheritedcall: boolean);
  1008. var
  1009. opc: tasmop;
  1010. begin
  1011. {
  1012. invoke types:
  1013. * invokeinterface: call method from an interface
  1014. * invokespecial: invoke a constructor, method in a superclass,
  1015. or private instance method
  1016. * invokestatic: invoke a class method (private or not)
  1017. * invokevirtual: invoke a regular method
  1018. }
  1019. case pd.owner.symtabletype of
  1020. globalsymtable,
  1021. staticsymtable,
  1022. localsymtable:
  1023. { regular and nested procedures are turned into static methods }
  1024. opc:=a_invokestatic;
  1025. objectsymtable:
  1026. begin
  1027. case tobjectdef(pd.owner.defowner).objecttype of
  1028. odt_javaclass:
  1029. begin
  1030. if (po_staticmethod in pd.procoptions) then
  1031. opc:=a_invokestatic
  1032. else if (pd.visibility=vis_private) or
  1033. (pd.proctypeoption=potype_constructor) or
  1034. inheritedcall then
  1035. opc:=a_invokespecial
  1036. else
  1037. opc:=a_invokevirtual;
  1038. end;
  1039. odt_interfacejava:
  1040. { static interface methods are not allowed }
  1041. opc:=a_invokeinterface;
  1042. else
  1043. internalerror(2010122601);
  1044. end;
  1045. end;
  1046. else
  1047. internalerror(2010122602);
  1048. end;
  1049. list.concat(taicpu.op_sym(opc,current_asmdata.RefAsmSymbol(s)));
  1050. end;
  1051. procedure create_hlcodegen;
  1052. begin
  1053. hlcg:=thlcgjvm.create;
  1054. create_codegen;
  1055. end;
  1056. end.