hlcgcpu.pas 42 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127
  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;
  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. { in case of an array, the array base address and index have to be
  95. put on the evaluation stack before the stored value; similarly, for
  96. fields the self pointer has to be loaded first. Also checks whether
  97. the reference is valid. If dup is true, the necessary values are stored
  98. twice. Returns how many stack slots have been consumed, disregarding
  99. the "dup". }
  100. function prepare_stack_for_ref(list: TAsmList; const ref: treference; dup: boolean): longint;
  101. function def2regtyp(def: tdef): tregistertype;
  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. 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. function thlcgjvm.prepare_stack_for_ref(list: TAsmList; const ref: treference; dup: boolean): longint;
  422. var
  423. href: treference;
  424. begin
  425. result:=0;
  426. { fake location that indicates the value is already on the stack? }
  427. if (ref.base=NR_EVAL_STACK_BASE) then
  428. exit;
  429. if ref.arrayreftype=art_none then
  430. begin
  431. { non-array accesses cannot have an index reg }
  432. if ref.index<>NR_NO then
  433. internalerror(2010120509);
  434. if (ref.base<>NR_NO) then
  435. begin
  436. if (ref.base<>NR_STACK_POINTER_REG) then
  437. begin
  438. { regular field -> load self on the stack }
  439. a_load_reg_stack(list,voidpointertype,ref.base);
  440. if dup then
  441. begin
  442. list.concat(taicpu.op_none(a_dup));
  443. incstack(1);
  444. end;
  445. { field name/type encoded in symbol, no index/offset }
  446. if not assigned(ref.symbol) or
  447. (ref.offset<>0) then
  448. internalerror(2010120524);
  449. result:=1;
  450. end
  451. else
  452. begin
  453. { local variable -> offset encoded in opcode and nothing to
  454. do here, except for checking that it's a valid reference }
  455. if assigned(ref.symbol) then
  456. internalerror(2010120523);
  457. end;
  458. end
  459. else
  460. begin
  461. { static field -> nothing to do here, except for validity check }
  462. if not assigned(ref.symbol) or
  463. (ref.offset<>0) then
  464. internalerror(2010120525);
  465. end;
  466. end
  467. else
  468. begin
  469. { arrays have implicit dereference -> pointer to array must have been
  470. loaded into base reg }
  471. if (ref.base=NR_NO) or
  472. (ref.base=NR_STACK_POINTER_REG) then
  473. internalerror(2010120511);
  474. if assigned(ref.symbol) then
  475. internalerror(2010120512);
  476. { stack: ... -> ..., arrayref, index }
  477. { load array base address }
  478. a_load_reg_stack(list,voidpointertype,ref.base);
  479. { index can either be in a register, or located in a simple memory
  480. location (since we have to load it anyway) }
  481. if ref.arrayreftype=art_indexreg then
  482. begin
  483. if ref.index=NR_NO then
  484. internalerror(2010120513);
  485. { all array indices in Java are 32 bit ints }
  486. a_load_reg_stack(list,s32inttype,ref.index);
  487. end
  488. else
  489. begin
  490. reference_reset_base(href,ref.indexbase,ref.indexoffset,4);
  491. href.symbol:=href.indexsymbol;
  492. a_load_ref_stack(list,s32inttype,href,prepare_stack_for_ref(list,href,false));
  493. end;
  494. { adjustment of the index }
  495. if ref.offset<>0 then
  496. a_op_const_stack(list,OP_ADD,s32inttype,ref.offset);
  497. if dup then
  498. begin
  499. list.concat(taicpu.op_none(a_dup2));
  500. incstack(2);
  501. end;
  502. result:=2;
  503. end;
  504. end;
  505. procedure thlcgjvm.a_load_const_reg(list: TAsmList; tosize: tdef; a: aint; register: tregister);
  506. begin
  507. a_load_const_stack(list,tosize,a,def2regtyp(tosize));
  508. a_load_stack_reg(list,tosize,register);
  509. end;
  510. procedure thlcgjvm.a_load_const_ref(list: TAsmList; tosize: tdef; a: aint; const ref: treference);
  511. var
  512. extra_slots: longint;
  513. begin
  514. extra_slots:=prepare_stack_for_ref(list,ref,false);
  515. a_load_const_stack(list,tosize,a,def2regtyp(tosize));
  516. a_load_stack_ref(list,tosize,ref,extra_slots);
  517. decstack(extra_slots);
  518. end;
  519. procedure thlcgjvm.a_load_reg_ref(list: TAsmList; fromsize, tosize: tdef; register: tregister; const ref: treference);
  520. var
  521. extra_slots: longint;
  522. begin
  523. extra_slots:=prepare_stack_for_ref(list,ref,false);
  524. a_load_reg_stack(list,fromsize,register);
  525. a_load_stack_ref(list,tosize,ref,extra_slots);
  526. decstack(extra_slots);
  527. end;
  528. procedure thlcgjvm.a_load_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister);
  529. begin
  530. a_load_reg_stack(list,fromsize,reg1);
  531. if def2regtyp(fromsize)=R_INTREGISTER then
  532. resize_stack_int_val(list,def_cgsize(fromsize),def_cgsize(tosize),false);
  533. a_load_stack_reg(list,tosize,reg2);
  534. end;
  535. procedure thlcgjvm.a_load_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; register: tregister);
  536. var
  537. extra_slots: longint;
  538. begin
  539. extra_slots:=prepare_stack_for_ref(list,ref,false);
  540. a_load_ref_stack(list,fromsize,ref,extra_slots);
  541. if def2regtyp(fromsize)=R_INTREGISTER then
  542. resize_stack_int_val(list,def_cgsize(fromsize),def_cgsize(tosize),false);
  543. a_load_stack_reg(list,tosize,register);
  544. end;
  545. procedure thlcgjvm.a_load_ref_ref(list: TAsmList; fromsize, tosize: tdef; const sref: treference; const dref: treference);
  546. var
  547. extra_sslots,
  548. extra_dslots: longint;
  549. begin
  550. { make sure the destination reference is on top, since in the end the
  551. order has to be "destref, value" -> first create "destref, sourceref" }
  552. extra_dslots:=prepare_stack_for_ref(list,dref,false);
  553. extra_sslots:=prepare_stack_for_ref(list,sref,false);
  554. a_load_ref_stack(list,fromsize,sref,extra_sslots);
  555. if def2regtyp(fromsize)=R_INTREGISTER then
  556. resize_stack_int_val(list,def_cgsize(fromsize),def_cgsize(tosize),dref.arrayreftype<>art_none);
  557. a_load_stack_ref(list,tosize,dref,extra_dslots);
  558. end;
  559. procedure thlcgjvm.a_loadaddr_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; r: tregister);
  560. begin
  561. internalerror(2010120534);
  562. end;
  563. procedure thlcgjvm.a_op_const_reg(list: TAsmList; Op: TOpCG; size: tdef; a: Aint; reg: TRegister);
  564. begin
  565. a_op_const_reg_reg(list,op,size,a,reg,reg);
  566. end;
  567. procedure thlcgjvm.a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tdef; a: aint; src, dst: tregister);
  568. begin
  569. a_load_reg_stack(list,size,src);
  570. a_op_const_stack(list,op,size,a);
  571. a_load_stack_reg(list,size,dst);
  572. end;
  573. procedure thlcgjvm.a_op_const_ref(list: TAsmList; Op: TOpCG; size: tdef; a: Aint; const ref: TReference);
  574. var
  575. extra_slots: longint;
  576. begin
  577. extra_slots:=prepare_stack_for_ref(list,ref,true);
  578. { TODO, here or in peepholeopt: use iinc when possible }
  579. a_load_ref_stack(list,size,ref,extra_slots);
  580. a_op_const_stack(list,op,size,a);
  581. a_load_stack_ref(list,size,ref,extra_slots);
  582. end;
  583. procedure thlcgjvm.a_op_ref_reg(list: TAsmList; Op: TOpCG; size: tdef; const ref: TReference; reg: TRegister);
  584. begin
  585. a_load_reg_stack(list,size,reg);
  586. a_op_ref_stack(list,op,size,ref);
  587. a_load_stack_reg(list,size,reg);
  588. end;
  589. procedure thlcgjvm.a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tdef; src1, src2, dst: tregister);
  590. begin
  591. a_load_reg_stack(list,size,src2);
  592. a_op_reg_stack(list,op,size,src1);
  593. a_load_stack_reg(list,size,dst);
  594. end;
  595. procedure thlcgjvm.a_op_reg_reg(list: TAsmList; Op: TOpCG; size: tdef; reg1, reg2: TRegister);
  596. begin
  597. a_op_reg_reg_reg(list,op,size,reg1,reg2,reg2);
  598. end;
  599. procedure thlcgjvm.a_cmp_const_ref_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: aint; const ref: treference; l: tasmlabel);
  600. begin
  601. a_load_const_stack(list,size,maybe_adjust_cmp_constval(size,cmp_op,a),R_INTREGISTER);
  602. if ref.base<>NR_EVAL_STACK_BASE then
  603. a_load_ref_stack(list,size,ref,prepare_stack_for_ref(list,ref,false))
  604. else
  605. list.concat(taicpu.op_none(a_swap));
  606. maybe_adjust_cmp_stackval(list,size,cmp_op);
  607. a_cmp_stack_label(list,size,cmp_op,l);
  608. end;
  609. procedure thlcgjvm.a_cmp_const_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: aint; reg: tregister; l: tasmlabel);
  610. begin
  611. a_load_const_stack(list,size,maybe_adjust_cmp_constval(size,cmp_op,a),R_INTREGISTER);
  612. a_load_reg_stack(list,size,reg);
  613. maybe_adjust_cmp_stackval(list,size,cmp_op);
  614. a_cmp_stack_label(list,size,cmp_op,l);
  615. end;
  616. procedure thlcgjvm.a_cmp_ref_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; const ref: treference; reg: tregister; l: tasmlabel);
  617. begin
  618. if ref.base<>NR_EVAL_STACK_BASE then
  619. a_load_ref_stack(list,size,ref,prepare_stack_for_ref(list,ref,false));
  620. maybe_adjust_cmp_stackval(list,size,cmp_op);
  621. a_load_reg_stack(list,size,reg);
  622. maybe_adjust_cmp_stackval(list,size,cmp_op);
  623. a_cmp_stack_label(list,size,cmp_op,l);
  624. end;
  625. procedure thlcgjvm.a_cmp_reg_ref_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg: tregister; const ref: treference; l: tasmlabel);
  626. begin
  627. a_load_reg_stack(list,size,reg);
  628. maybe_adjust_cmp_stackval(list,size,cmp_op);
  629. if ref.base<>NR_EVAL_STACK_BASE then
  630. a_load_ref_stack(list,size,ref,prepare_stack_for_ref(list,ref,false))
  631. else
  632. list.concat(taicpu.op_none(a_swap));
  633. maybe_adjust_cmp_stackval(list,size,cmp_op);
  634. a_cmp_stack_label(list,size,cmp_op,l);
  635. end;
  636. procedure thlcgjvm.a_cmp_reg_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);
  637. begin
  638. a_load_reg_stack(list,size,reg1);
  639. maybe_adjust_cmp_stackval(list,size,cmp_op);
  640. a_load_reg_stack(list,size,reg2);
  641. maybe_adjust_cmp_stackval(list,size,cmp_op);
  642. a_cmp_stack_label(list,size,cmp_op,l);
  643. end;
  644. procedure thlcgjvm.a_jmp_always(list: TAsmList; l: tasmlabel);
  645. begin
  646. list.concat(taicpu.op_sym(a_goto,current_asmdata.RefAsmSymbol(l.name)));
  647. end;
  648. procedure thlcgjvm.a_loadfpu_ref_ref(list: TAsmList; fromsize, tosize: tdef; const ref1, ref2: treference);
  649. var
  650. dstack_slots: longint;
  651. begin
  652. dstack_slots:=prepare_stack_for_ref(list,ref2,false);
  653. a_load_ref_stack(list,fromsize,ref1,prepare_stack_for_ref(list,ref1,false));
  654. resizestackfpuval(list,def_cgsize(fromsize),def_cgsize(tosize));
  655. a_load_stack_ref(list,tosize,ref2,dstack_slots);
  656. end;
  657. procedure thlcgjvm.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister);
  658. begin
  659. a_load_ref_stack(list,fromsize,ref,prepare_stack_for_ref(list,ref,false));
  660. resizestackfpuval(list,def_cgsize(fromsize),def_cgsize(tosize));
  661. a_load_stack_reg(list,tosize,reg);
  662. end;
  663. procedure thlcgjvm.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tdef; reg: tregister; const ref: treference);
  664. var
  665. dstack_slots: longint;
  666. begin
  667. dstack_slots:=prepare_stack_for_ref(list,ref,false);
  668. a_load_reg_stack(list,fromsize,reg);
  669. resizestackfpuval(list,def_cgsize(fromsize),def_cgsize(tosize));
  670. a_load_stack_ref(list,tosize,ref,dstack_slots);
  671. end;
  672. procedure thlcgjvm.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister);
  673. begin
  674. a_load_reg_stack(list,fromsize,reg1);
  675. resizestackfpuval(list,def_cgsize(fromsize),def_cgsize(tosize));
  676. a_load_stack_reg(list,tosize,reg2);
  677. end;
  678. procedure thlcgjvm.g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean);
  679. begin
  680. { the localsize is based on tg.lasttemp -> already in terms of stack
  681. slots rather than bytes }
  682. list.concat(tai_directive.Create(asd_jlimit,'locals '+tostr(localsize)));
  683. list.concat(tai_directive.Create(asd_jlimit,'stack '+tostr(fmaxevalstackheight)));
  684. end;
  685. procedure thlcgjvm.g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean);
  686. begin
  687. // TODO: must be made part of returning the result, because ret opcode
  688. // depends on that
  689. list.concat(taicpu.op_none(a_return));
  690. end;
  691. procedure thlcgjvm.record_generated_code_for_procdef(pd: tprocdef; code, data: TAsmList);
  692. begin
  693. { add something to the al_procedures list as well, because if all al_*
  694. lists are empty, the assembler writer isn't called }
  695. if not code.empty and
  696. current_asmdata.asmlists[al_procedures].empty then
  697. current_asmdata.asmlists[al_procedures].concat(tai_align.Create(4));
  698. pd.exprasmlist:=TAsmList.create;
  699. pd.exprasmlist.concatlist(code);
  700. if assigned(data) and
  701. not data.empty then
  702. internalerror(2010122801);
  703. end;
  704. procedure thlcgjvm.a_load_stack_reg(list: TAsmList; size: tdef; reg: tregister);
  705. var
  706. opc: tasmop;
  707. finishandval: aint;
  708. begin
  709. opc:=loadstoreopc(size,false,false,finishandval);
  710. list.concat(taicpu.op_reg(opc,reg));
  711. decstack(1+ord(size.size>4));
  712. end;
  713. procedure thlcgjvm.a_load_stack_ref(list: TAsmList; size: tdef; const ref: treference; extra_slots: longint);
  714. var
  715. opc: tasmop;
  716. finishandval: aint;
  717. begin
  718. { fake location that indicates the value has to remain on the stack }
  719. if ref.base=NR_EVAL_STACK_BASE then
  720. exit;
  721. opc:=loadstoreopcref(size,false,ref,finishandval);
  722. if ref.arrayreftype=art_none then
  723. list.concat(taicpu.op_ref(opc,ref))
  724. else
  725. list.concat(taicpu.op_none(opc));
  726. decstack(1+ord(size.size>4)+extra_slots);
  727. end;
  728. procedure thlcgjvm.a_load_reg_stack(list: TAsmList; size: tdef; reg: tregister);
  729. var
  730. opc: tasmop;
  731. finishandval: aint;
  732. begin
  733. opc:=loadstoreopc(size,true,false,finishandval);
  734. list.concat(taicpu.op_reg(opc,reg));
  735. if finishandval<>-1 then
  736. a_op_const_stack(list,OP_AND,size,finishandval);
  737. incstack(1+ord(size.size>4));
  738. end;
  739. procedure thlcgjvm.a_load_ref_stack(list: TAsmList; size: tdef; const ref: treference; extra_slots: longint);
  740. var
  741. opc: tasmop;
  742. finishandval: aint;
  743. begin
  744. { fake location that indicates the value is already on the stack? }
  745. if (ref.base=NR_EVAL_STACK_BASE) then
  746. exit;
  747. opc:=loadstoreopcref(size,true,ref,finishandval);
  748. if ref.arrayreftype=art_none then
  749. list.concat(taicpu.op_ref(opc,ref))
  750. else
  751. list.concat(taicpu.op_none(opc));
  752. if finishandval<>-1 then
  753. a_op_const_stack(list,OP_AND,size,finishandval);
  754. incstack(1+ord(size.size>4)-extra_slots);
  755. end;
  756. function thlcgjvm.def2regtyp(def: tdef): tregistertype;
  757. begin
  758. case def.typ of
  759. enumdef,
  760. orddef,
  761. setdef:
  762. result:=R_INTREGISTER;
  763. stringdef,
  764. pointerdef,
  765. classrefdef,
  766. objectdef,
  767. procvardef,
  768. procdef,
  769. arraydef :
  770. result:=R_ADDRESSREGISTER;
  771. floatdef:
  772. result:=R_FPUREGISTER;
  773. filedef,
  774. recorddef,
  775. variantdef:
  776. internalerror(2010120507);
  777. else
  778. internalerror(2010120506);
  779. end;
  780. end;
  781. function thlcgjvm.loadstoreopcref(def: tdef; isload: boolean; const ref: treference; out finishandval: aint): tasmop;
  782. const
  783. { isload static }
  784. getputopc: array[boolean,boolean] of tasmop =
  785. ((a_putfield,a_putstatic),
  786. (a_getfield,a_getstatic));
  787. var
  788. size: aint;
  789. begin
  790. if assigned(ref.symbol) then
  791. begin
  792. finishandval:=-1;
  793. { -> either a global (static) field, or a regular field. If a regular
  794. field, then ref.base contains the self pointer, otherwise
  795. ref.base=NR_NO. In both cases, the symbol contains all other
  796. information (combined field name and type descriptor) }
  797. result:=getputopc[isload,ref.base=NR_NO];
  798. end
  799. else
  800. result:=loadstoreopc(def,isload,ref.arrayreftype<>art_none,finishandval);
  801. end;
  802. function thlcgjvm.loadstoreopc(def: tdef; isload, isarray: boolean; out finishandval: aint): tasmop;
  803. var
  804. size: longint;
  805. begin
  806. finishandval:=-1;
  807. case def2regtyp(def) of
  808. R_INTREGISTER:
  809. begin
  810. size:=def.size;
  811. if not isarray then
  812. begin
  813. case size of
  814. 1,2,3,4:
  815. if isload then
  816. result:=a_iload
  817. else
  818. result:=a_istore;
  819. 8:
  820. if isload then
  821. result:=a_lload
  822. else
  823. result:=a_lstore;
  824. end;
  825. end
  826. { array }
  827. else if isload then
  828. begin
  829. case size of
  830. 1:
  831. begin
  832. result:=a_baload;
  833. if not is_signed(def) then
  834. finishandval:=255;
  835. end;
  836. 2:
  837. begin
  838. if is_widechar(def) then
  839. result:=a_caload
  840. else
  841. begin
  842. result:=a_saload;
  843. { if we'd treat arrays of word as "array of widechar" we
  844. could use a_caload, but that would make for even more
  845. awkward interfacing with external Java code }
  846. if not is_signed(def) then
  847. finishandval:=65535;
  848. end;
  849. end;
  850. 4: result:=a_iaload;
  851. 8: result:=a_laload;
  852. else
  853. internalerror(2010120503);
  854. end
  855. end
  856. else
  857. begin
  858. case size of
  859. 1: result:=a_bastore;
  860. 2: if not is_widechar(def) then
  861. result:=a_sastore
  862. else
  863. result:=a_castore;
  864. 4: result:=a_iastore;
  865. 8: result:=a_lastore;
  866. else
  867. internalerror(2010120508);
  868. end
  869. end
  870. end;
  871. R_ADDRESSREGISTER:
  872. if not isarray then
  873. if isload then
  874. result:=a_aload
  875. else
  876. result:=a_astore
  877. else if isload then
  878. result:=a_aaload
  879. else
  880. result:=a_aastore;
  881. R_FPUREGISTER:
  882. begin
  883. case tfloatdef(def).floattype of
  884. s32real:
  885. if not isarray then
  886. if isload then
  887. result:=a_fload
  888. else
  889. result:=a_fstore
  890. else if isload then
  891. result:=a_faload
  892. else
  893. result:=a_fastore;
  894. s64real:
  895. if not isarray then
  896. if isload then
  897. result:=a_dload
  898. else
  899. result:=a_dstore
  900. else if isload then
  901. result:=a_daload
  902. else
  903. result:=a_dastore;
  904. else
  905. internalerror(2010120504);
  906. end
  907. end
  908. else
  909. internalerror(2010120502);
  910. end;
  911. end;
  912. procedure thlcgjvm.resize_stack_int_val(list: TAsmList; fromsize, tosize: tcgsize; forarraystore: boolean);
  913. begin
  914. if fromsize in [OS_S64,OS_64] then
  915. begin
  916. if not(tosize in [OS_S64,OS_64]) then
  917. begin
  918. { truncate }
  919. list.concat(taicpu.op_none(a_l2i));
  920. decstack(1);
  921. end;
  922. end
  923. else if tosize in [OS_S64,OS_64] then
  924. begin
  925. { extend }
  926. list.concat(taicpu.op_none(a_i2l));
  927. incstack(1);
  928. { if it was an unsigned 32 bit value, remove sign extension }
  929. if fromsize=OS_32 then
  930. a_op_const_stack(list,OP_AND,s64inttype,cardinal($ffffffff));
  931. end;
  932. { if the value is immediately stored to an array afterwards, the store
  933. instruction will properly truncate the value; otherwise we may need
  934. additional truncation, except for 64/32 bit conversions, which are
  935. already handled above }
  936. if not forarraystore and
  937. (not(fromsize in [OS_S64,OS_64,OS_32,OS_S32]) or
  938. not(tosize in [OS_S64,OS_64,OS_32,OS_S32])) and
  939. (tcgsize2size[fromsize]>tcgsize2size[tosize]) or
  940. ((tcgsize2size[fromsize]=tcgsize2size[tosize]) and
  941. (fromsize<>tosize)) or
  942. { needs to mask out the sign in the top 16 bits }
  943. ((fromsize=OS_S8) and
  944. (tosize=OS_16)) then
  945. case tosize of
  946. OS_8:
  947. a_op_const_stack(list,OP_AND,s32inttype,255);
  948. OS_S8:
  949. list.concat(taicpu.op_none(a_i2b));
  950. OS_16:
  951. list.concat(taicpu.op_none(a_i2c));
  952. OS_S16:
  953. list.concat(taicpu.op_none(a_i2s));
  954. end;
  955. end;
  956. procedure thlcgjvm.resizestackfpuval(list: TAsmList; fromsize, tosize: tcgsize);
  957. begin
  958. if (fromsize=OS_F32) and
  959. (tosize=OS_F64) then
  960. begin
  961. list.concat(taicpu.op_none(a_f2d));
  962. incstack(1);
  963. end
  964. else if (fromsize=OS_F64) and
  965. (tosize=OS_F32) then
  966. begin
  967. list.concat(taicpu.op_none(a_d2f));
  968. decstack(1);
  969. end;
  970. end;
  971. procedure thlcgjvm.maybepreparedivu32(list: TAsmList; var op: topcg; size: tdef; out isdivu32: boolean);
  972. begin
  973. if (op=OP_DIV) and
  974. (def_cgsize(size)=OS_32) then
  975. begin
  976. { needs zero-extension to 64 bit, because the JVM only supports
  977. signed divisions }
  978. resize_stack_int_val(list,OS_32,OS_S64,false);
  979. op:=OP_IDIV;
  980. isdivu32:=true;
  981. end
  982. else
  983. isdivu32:=false;
  984. end;
  985. procedure thlcgjvm.a_call_name_intern(list: TAsmList; pd: tprocdef; const s: string; inheritedcall: boolean);
  986. var
  987. opc: tasmop;
  988. begin
  989. {
  990. invoke types:
  991. * invokeinterface: call method from an interface
  992. * invokespecial: invoke a constructor, method in a superclass,
  993. or private instance method
  994. * invokestatic: invoke a class method (private or not)
  995. * invokevirtual: invoke a regular method
  996. }
  997. case pd.owner.symtabletype of
  998. globalsymtable,
  999. staticsymtable,
  1000. localsymtable:
  1001. { regular and nested procedures are turned into static methods }
  1002. opc:=a_invokestatic;
  1003. objectsymtable:
  1004. begin
  1005. case tobjectdef(pd.owner.defowner).objecttype of
  1006. odt_javaclass:
  1007. begin
  1008. if (po_staticmethod in pd.procoptions) then
  1009. opc:=a_invokestatic
  1010. else if (pd.visibility=vis_private) or
  1011. (pd.proctypeoption=potype_constructor) or
  1012. inheritedcall then
  1013. opc:=a_invokespecial
  1014. else
  1015. opc:=a_invokevirtual;
  1016. end;
  1017. odt_interfacejava:
  1018. { static interface methods are not allowed }
  1019. opc:=a_invokeinterface;
  1020. else
  1021. internalerror(2010122601);
  1022. end;
  1023. end;
  1024. else
  1025. internalerror(2010122602);
  1026. end;
  1027. list.concat(taicpu.op_sym(opc,current_asmdata.RefAsmSymbol(s)));
  1028. end;
  1029. procedure create_hlcodegen;
  1030. begin
  1031. hlcg:=thlcgjvm.create;
  1032. create_codegen;
  1033. end;
  1034. end.