hlcgcpu.pas 43 KB

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