hlcgcpu.pas 74 KB

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