hlcgcpu.pas 41 KB

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