hlcgllvm.pas 85 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158
  1. {
  2. Copyright (c) 2010, 2013 by Jonas Maebe
  3. Member of the Free Pascal development team
  4. This unit implements the LLVM 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 hlcgllvm;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,cclasses,
  23. aasmbase,aasmdata,
  24. symbase,symconst,symtype,symdef,symsym,
  25. cpubase, hlcgobj, cgbase, cgutils, parabase, tgobj;
  26. type
  27. { thlcgllvm }
  28. thlcgllvm = class(thlcgobj)
  29. constructor create;
  30. procedure a_load_reg_cgpara(list: TAsmList; size: tdef; r: tregister; const cgpara: TCGPara); override;
  31. procedure a_load_ref_cgpara(list: TAsmList; size: tdef; const r: treference; const cgpara: TCGPara); override;
  32. procedure a_load_const_cgpara(list: TAsmList; tosize: tdef; a: tcgint; const cgpara: TCGPara); override;
  33. protected
  34. procedure a_load_ref_cgpara_init_src(list: TAsmList; const para: tcgpara; const initialref: treference; var refsize: tdef; out newref: treference);
  35. public
  36. procedure getcpuregister(list: TAsmList; r: Tregister); override;
  37. procedure ungetcpuregister(list: TAsmList; r: Tregister); override;
  38. procedure alloccpuregisters(list: TAsmList; rt: Tregistertype; const r: Tcpuregisterset); override;
  39. procedure allocallcpuregisters(list: TAsmList); override;
  40. procedure deallocallcpuregisters(list: TAsmList); override;
  41. procedure a_bit_test_reg_reg_reg(list: TAsmList; bitnumbersize, valuesize, destsize: tdef; bitnumber, value, destreg: tregister); override;
  42. procedure a_bit_set_reg_reg(list: TAsmList; doset: boolean; bitnumbersize, destsize: tdef; bitnumber, dest: tregister); override;
  43. protected
  44. procedure a_call_common(list: TAsmList; pd: tabstractprocdef; const paras: array of pcgpara; const forceresdef: tdef; out res: tregister; out hlretdef: tdef; out llvmretdef: tdef; out callparas: tfplist);
  45. public
  46. function a_call_name(list : TAsmList;pd : tprocdef;const s : TSymStr; const paras: array of pcgpara; forceresdef: tdef; weak: boolean): tcgpara;override;
  47. function a_call_reg(list: TAsmList; pd: tabstractprocdef; reg: tregister; const paras: array of pcgpara): tcgpara; override;
  48. procedure a_load_const_reg(list : TAsmList;tosize : tdef;a : tcgint;register : tregister);override;
  49. procedure a_load_const_ref(list: TAsmList; tosize: tdef; a: tcgint; const ref: treference);override;
  50. procedure a_load_reg_ref(list : TAsmList;fromsize, tosize : tdef;register : tregister;const ref : treference);override;
  51. procedure a_load_reg_reg(list : TAsmList;fromsize, tosize : tdef;reg1,reg2 : tregister);override;
  52. protected
  53. procedure gen_load_refaddrfull_anyreg(list: TAsmList; fromsize, tosize : tdef; const simpleref: treference; register: tregister; shuffle: pmmshuffle);
  54. function handle_agg_load_ref_anyreg(list: TasmList; var fromsize, tosize: tdef; var simpleref: treference; register: tregister; shuffle: pmmshuffle): boolean;
  55. public
  56. procedure a_load_ref_reg(list : TAsmList;fromsize, tosize : tdef;const ref : treference;register : tregister);override;
  57. procedure a_load_ref_ref(list: TAsmList; fromsize, tosize: tdef; const sref: treference; const dref: treference); override;
  58. protected
  59. procedure a_loadaddr_ref_reg_intern(list : TAsmList;fromsize, tosize : tdef;const ref : treference;r : tregister; makefromsizepointer: boolean);
  60. public
  61. procedure a_loadaddr_ref_reg(list : TAsmList;fromsize, tosize : tdef;const ref : treference;r : tregister);override;
  62. procedure a_op_const_reg(list: TAsmList; Op: TOpCG; size: tdef; a: tcgint; reg: TRegister); override;
  63. procedure a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tdef; a: tcgint; src, dst: tregister); override;
  64. procedure a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tdef; src1, src2, dst: tregister); override;
  65. procedure a_op_reg_reg(list: TAsmList; Op: TOpCG; size: tdef; reg1, reg2: TRegister); override;
  66. procedure a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tdef; a: tcgint; src, dst: tregister;setflags : boolean;var ovloc : tlocation); override;
  67. procedure a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tdef; src1, src2, dst: tregister;setflags : boolean;var ovloc : tlocation); override;
  68. procedure a_cmp_const_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel); override;
  69. procedure a_cmp_reg_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel); override;
  70. procedure a_jmp_always(list : TAsmList;l: tasmlabel); override;
  71. procedure g_unreachable(list: TAsmList); override;
  72. procedure g_concatcopy(list : TAsmList;size: tdef; const source,dest : treference);override;
  73. procedure a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister); override;
  74. procedure a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tdef; reg: tregister; const ref: treference); override;
  75. procedure a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister); override;
  76. procedure gen_proc_symbol(list: TAsmList); override;
  77. procedure handle_external_proc(list: TAsmList; pd: tprocdef; const importname: TSymStr); override;
  78. procedure g_proc_entry(list : TAsmList;localsize : longint;nostackframe:boolean); override;
  79. procedure g_proc_exit(list : TAsmList;parasize:longint;nostackframe:boolean); override;
  80. protected
  81. procedure gen_load_uninitialized_function_result(list: TAsmList; pd: tprocdef; resdef: tdef; const resloc: tcgpara); override;
  82. public
  83. procedure g_overflowcheck(list: TAsmList; const Loc: tlocation; def: tdef); override;
  84. procedure g_overflowCheck_loc(List:TAsmList;const Loc:TLocation;def:TDef;var ovloc : tlocation); override;
  85. procedure g_ptrtypecast_reg(list: TAsmList; fromdef, todef: tdef; var reg: tregister); override;
  86. procedure g_ptrtypecast_ref(list: TAsmList; fromdef, todef: tdef; var ref: treference); override;
  87. procedure g_set_addr_nonbitpacked_field_ref(list: TAsmList; recdef: tabstractrecorddef; field: tfieldvarsym; var recref: treference); override;
  88. procedure a_loadmm_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister; shuffle: pmmshuffle); override;
  89. procedure a_loadmm_reg_ref(list: TAsmList; fromsize, tosize: tdef; reg: tregister; const ref: treference; shuffle: pmmshuffle); override;
  90. procedure a_loadmm_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister; shuffle: pmmshuffle); override;
  91. procedure a_opmm_reg_reg(list: TAsmList; Op: TOpCG; size: tdef; src, dst: tregister; shuffle: pmmshuffle); override;
  92. procedure a_loadmm_intreg_reg(list: TAsmList; fromsize, tosize: tdef; intreg, mmreg: tregister; shuffle: pmmshuffle); override;
  93. procedure a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize: tdef; mmreg, intreg: tregister; shuffle: pmmshuffle); override;
  94. function get_call_result_cgpara(pd: tabstractprocdef; forceresdef: tdef): tcgpara; override;
  95. protected
  96. procedure gen_load_loc_function_result(list: TAsmList; vardef: tdef; const l: tlocation); override;
  97. public
  98. procedure gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara); override;
  99. procedure gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean); override;
  100. {$ifdef cpuflags}
  101. { llvm doesn't have flags, but cpuflags is defined in case the real cpu
  102. has flags and we have to override the abstract methods to prevent
  103. warnings }
  104. procedure a_jmp_flags(list: TAsmList; const f: TResFlags; l: tasmlabel); override;
  105. procedure g_flags2reg(list: TAsmList; size: tdef; const f: tresflags; reg: TRegister); override;
  106. procedure g_flags2ref(list: TAsmList; size: tdef; const f: tresflags; const ref: TReference); override;
  107. {$endif cpuflags}
  108. { unimplemented or unnecessary routines }
  109. procedure a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tdef; src, dst: tregister); override;
  110. procedure g_stackpointer_alloc(list: TAsmList; size: longint); override;
  111. procedure g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint); override;
  112. procedure g_adjust_self_value(list: TAsmList; procdef: tprocdef; ioffset: aint); override;
  113. procedure g_local_unwind(list: TAsmList; l: TAsmLabel); override;
  114. procedure gen_stack_check_size_para(list: TAsmList); override;
  115. procedure gen_stack_check_call(list: TAsmList); override;
  116. procedure varsym_set_localloc(list: TAsmList; vs: tabstractnormalvarsym); override;
  117. procedure paravarsym_set_initialloc_to_paraloc(vs: tparavarsym); override;
  118. procedure g_external_wrapper(list: TAsmList; procdef: tprocdef; const wrappername, externalname: string; global: boolean); override;
  119. { def is a pointerdef or implicit pointer type (class, classref, procvar,
  120. dynamic array, ...). }
  121. function make_simple_ref_ptr(list: TAsmList; const ref: treference; ptrdef: tdef): treference;
  122. { def is the type of the data stored in memory pointed to by ref, not
  123. a pointer to this type }
  124. function make_simple_ref(list: TAsmList; const ref: treference; def: tdef): treference;
  125. protected
  126. procedure paraloctoloc(const paraloc: pcgparalocation; out hloc: tlocation);
  127. procedure set_call_function_result(const list: TAsmList; const pd: tabstractprocdef; const llvmretdef, hlretdef: tdef; const resval: tregister; var retpara: tcgpara);
  128. end;
  129. implementation
  130. uses
  131. verbose,cutils,globals,fmodule,constexp,systems,
  132. defutil,llvmdef,llvmsym,
  133. aasmtai,aasmcpu,
  134. aasmllvm,llvmbase,llvminfo,tgllvm,
  135. symtable,symllvm,
  136. paramgr,
  137. pass_2,procinfo,llvmpi,cpuinfo,cgobj,cgllvm,cghlcpu,
  138. cgcpu,hlcgcpu;
  139. var
  140. create_hlcodegen_cpu: TProcedure = nil;
  141. const
  142. topcg2llvmop: array[topcg] of tllvmop =
  143. { OP_NONE OP_MOVE OP_ADD OP_AND OP_DIV OP_IDIV OP_IMUL OP_MUL }
  144. (la_none, la_none, la_add, la_and, la_udiv, la_sdiv, la_mul, la_mul,
  145. { OP_NEG OP_NOT OP_OR OP_SAR OP_SHL OP_SHR OP_SUB OP_XOR }
  146. la_none, la_none, la_or, la_ashr, la_shl, la_lshr, la_sub, la_xor,
  147. { OP_ROL OP_ROR }
  148. la_none, la_none);
  149. constructor thlcgllvm.create;
  150. begin
  151. inherited
  152. end;
  153. procedure thlcgllvm.a_load_reg_cgpara(list: TAsmList; size: tdef; r: tregister; const cgpara: TCGPara);
  154. begin
  155. if size<>llvm_metadatatype then
  156. begin
  157. inherited;
  158. exit;
  159. end;
  160. { overwrite with the reference to the metadata (stored in the register's supreg) }
  161. cgpara.location^.register:=r;
  162. end;
  163. procedure thlcgllvm.a_load_ref_cgpara(list: TAsmList; size: tdef; const r: treference; const cgpara: TCGPara);
  164. var
  165. tmpref, initialref, ref: treference;
  166. fielddef,
  167. orgsize: tdef;
  168. location: pcgparalocation;
  169. sizeleft,
  170. totaloffset: asizeint;
  171. paralocidx: longint;
  172. userecord: boolean;
  173. begin
  174. location:=cgpara.location;
  175. sizeleft:=cgpara.intsize;
  176. totaloffset:=0;
  177. orgsize:=size;
  178. a_load_ref_cgpara_init_src(list,cgpara,r,size,initialref);
  179. if initialref.refaddr=addr_full then
  180. begin
  181. cgpara.check_simple_location;
  182. location^.llvmvalueloc:=true;
  183. location^.llvmloc.loc:=LOC_CREFERENCE;
  184. location^.llvmloc.sym:=initialref.symbol;
  185. exit;
  186. end;
  187. userecord:=
  188. (orgsize<>size) and
  189. assigned(cgpara.location^.next);
  190. paralocidx:=0;
  191. fielddef:=nil;
  192. while assigned(location) do
  193. begin
  194. if userecord then
  195. begin
  196. { llvmparadef is a record in this case, with every field
  197. corresponding to a single paraloc (fielddef is unused, because
  198. it will be equivalent to location^.def -- see below) }
  199. g_setup_load_field_by_name(list,trecorddef(size),'F'+tostr(paralocidx),initialref,tmpref,fielddef);
  200. end
  201. else
  202. tmpref:=initialref;
  203. paramanager.allocparaloc(list,location);
  204. case location^.loc of
  205. LOC_REGISTER,LOC_CREGISTER:
  206. begin
  207. { byval parameter -> load the address rather than the value }
  208. if not location^.llvmvalueloc then
  209. a_loadaddr_ref_reg(list,tpointerdef(location^.def).pointeddef,location^.def,tmpref,location^.register)
  210. { if this parameter is split into multiple paralocs via
  211. record fields, load the current paraloc. The type of the
  212. paraloc and of the current record field will match by
  213. construction (the record is build from the paraloc
  214. types) }
  215. else if userecord then
  216. a_load_ref_reg(list,fielddef,location^.def,tmpref,location^.register)
  217. { if the parameter is passed in a single paraloc, the
  218. paraloc's type may be different from the declared type
  219. -> use the original complete parameter size as source so
  220. we can insert a type conversion if necessary }
  221. else
  222. a_load_ref_reg(list,size,location^.def,tmpref,location^.register)
  223. end;
  224. LOC_REFERENCE,LOC_CREFERENCE:
  225. begin
  226. if assigned(location^.next) then
  227. internalerror(2010052906);
  228. reference_reset_base(ref,cpointerdef.getreusable(size),location^.reference.index,location^.reference.offset,ctempposinvalid,newalignment(cgpara.alignment,cgpara.intsize-sizeleft),[]);
  229. if (def_cgsize(size)<>OS_NO) and
  230. (size.size=sizeleft) and
  231. (sizeleft<=sizeof(aint)) then
  232. a_load_ref_ref(list,size,location^.def,tmpref,ref)
  233. else
  234. { use concatcopy, because the parameter can be larger than }
  235. { what the OS_* constants can handle }
  236. g_concatcopy(list,location^.def,tmpref,ref);
  237. end;
  238. LOC_MMREGISTER,LOC_CMMREGISTER:
  239. begin
  240. case location^.size of
  241. OS_F32,
  242. OS_F64,
  243. OS_F128:
  244. a_loadmm_ref_reg(list,location^.def,location^.def,tmpref,location^.register,mms_movescalar);
  245. OS_M8..OS_M128,
  246. OS_MS8..OS_MS128,
  247. OS_32..OS_128,
  248. { OS_NO is for records of non-power-of-two sizes that have to
  249. be passed in MM registers -> never scalar floats }
  250. OS_NO:
  251. a_loadmm_ref_reg(list,location^.def,location^.def,tmpref,location^.register,nil);
  252. else
  253. internalerror(2010053101);
  254. end;
  255. end
  256. else
  257. internalerror(2010053111);
  258. end;
  259. inc(totaloffset,tcgsize2size[location^.size]);
  260. dec(sizeleft,tcgsize2size[location^.size]);
  261. location:=location^.next;
  262. inc(paralocidx);
  263. end;
  264. end;
  265. procedure thlcgllvm.a_load_const_cgpara(list: TAsmList; tosize: tdef; a: tcgint; const cgpara: TCGPara);
  266. begin
  267. if is_ordinal(cgpara.def) then
  268. begin
  269. cgpara.check_simple_location;
  270. paramanager.alloccgpara(list,cgpara);
  271. if cgpara.location^.shiftval<0 then
  272. a:=a shl -cgpara.location^.shiftval;
  273. cgpara.location^.llvmloc.loc:=LOC_CONSTANT;
  274. cgpara.location^.llvmloc.value:=a;
  275. end
  276. else
  277. inherited;
  278. end;
  279. procedure thlcgllvm.a_load_ref_cgpara_init_src(list: TAsmList; const para: tcgpara; const initialref: treference; var refsize: tdef; out newref: treference);
  280. var
  281. newrefsize: tdef;
  282. reg: tregister;
  283. begin
  284. newrefsize:=llvmgetcgparadef(para,true,callerside);
  285. if (refsize<>newrefsize) and
  286. (initialref.refaddr<>addr_full) then
  287. begin
  288. reg:=getaddressregister(list,cpointerdef.getreusable(newrefsize));
  289. a_loadaddr_ref_reg(list,refsize,cpointerdef.getreusable(newrefsize),initialref,reg);
  290. reference_reset_base(newref,cpointerdef.getreusable(newrefsize),reg,0,initialref.temppos,initialref.alignment,initialref.volatility);
  291. refsize:=newrefsize;
  292. end
  293. else
  294. newref:=initialref;
  295. end;
  296. procedure thlcgllvm.getcpuregister(list: TAsmList; r: Tregister);
  297. begin
  298. { don't do anything }
  299. end;
  300. procedure thlcgllvm.ungetcpuregister(list: TAsmList; r: Tregister);
  301. begin
  302. { don't do anything }
  303. end;
  304. procedure thlcgllvm.alloccpuregisters(list: TAsmList; rt: Tregistertype; const r: Tcpuregisterset);
  305. begin
  306. { don't do anything }
  307. end;
  308. procedure thlcgllvm.allocallcpuregisters(list: TAsmList);
  309. begin
  310. { don't do anything }
  311. end;
  312. procedure thlcgllvm.deallocallcpuregisters(list: TAsmList);
  313. begin
  314. { don't do anything }
  315. end;
  316. procedure thlcgllvm.a_bit_test_reg_reg_reg(list: TAsmList; bitnumbersize, valuesize, destsize: tdef; bitnumber, value, destreg: tregister);
  317. var
  318. tmpbitnumberreg: tregister;
  319. begin
  320. { unlike other architectures, llvm requires the bitnumber register to
  321. have the same size as the shifted register }
  322. if bitnumbersize.size<>valuesize.size then
  323. begin
  324. tmpbitnumberreg:=hlcg.getintregister(list,valuesize);
  325. a_load_reg_reg(list,bitnumbersize,valuesize,bitnumber,tmpbitnumberreg);
  326. bitnumbersize:=valuesize;
  327. bitnumber:=tmpbitnumberreg;
  328. end;
  329. inherited;
  330. end;
  331. procedure thlcgllvm.a_bit_set_reg_reg(list: TAsmList; doset: boolean; bitnumbersize, destsize: tdef; bitnumber, dest: tregister);
  332. var
  333. tmpbitnumberreg: tregister;
  334. begin
  335. { unlike other architectures, llvm requires the bitnumber register to
  336. have the same size as the shifted register }
  337. if bitnumbersize.size<>destsize.size then
  338. begin
  339. tmpbitnumberreg:=hlcg.getintregister(list,destsize);
  340. a_load_reg_reg(list,bitnumbersize,destsize,bitnumber,tmpbitnumberreg);
  341. bitnumbersize:=destsize;
  342. bitnumber:=tmpbitnumberreg;
  343. end;
  344. inherited;
  345. end;
  346. function get_call_pd(pd: tabstractprocdef): tdef;
  347. begin
  348. if (pd.typ=procdef) or
  349. not pd.is_addressonly then
  350. { we get a pointerdef rather than a procvardef so that if we have to
  351. insert an external declaration for this procdef in llvmtype, we don't
  352. have to create another procdef from the procvardef we've just created.
  353. With a pointerdef, we can just get the pointeddef again. A pointerdef
  354. is also much cheaper to create, and in llvm a provardef is a "function
  355. pointer", so a pointer to a procdef is the same as a procvar as far
  356. as llvm is concerned }
  357. result:=cpointerdef.getreusable(pd)
  358. else
  359. result:=pd
  360. end;
  361. procedure thlcgllvm.a_call_common(list: TAsmList; pd: tabstractprocdef; const paras: array of pcgpara; const forceresdef: tdef; out res: tregister; out hlretdef: tdef; out llvmretdef: tdef; out callparas: tfplist);
  362. procedure load_ref_anyreg(def: tdef; const ref: treference; reg: tregister);
  363. begin
  364. case getregtype(reg) of
  365. R_INTREGISTER,
  366. R_ADDRESSREGISTER:
  367. begin
  368. a_load_ref_reg(list,def,def,ref,reg);
  369. end;
  370. R_FPUREGISTER:
  371. begin
  372. a_loadfpu_ref_reg(list,def,def,ref,reg);
  373. end;
  374. R_MMREGISTER:
  375. begin
  376. a_loadmm_ref_reg(list,def,def,ref,reg,mms_movescalar);
  377. end;
  378. else
  379. internalerror(2014012213);
  380. end;
  381. end;
  382. var
  383. i: longint;
  384. href: treference;
  385. callpara: pllvmcallpara;
  386. paraloc: pcgparalocation;
  387. firstparaloc: boolean;
  388. begin
  389. callparas:=tfplist.Create;
  390. for i:=0 to high(paras) do
  391. begin
  392. { skip parameters without data }
  393. if paras[i]^.isempty then
  394. continue;
  395. paraloc:=paras[i]^.location;
  396. firstparaloc:=true;
  397. while assigned(paraloc) do
  398. begin
  399. new(callpara);
  400. callpara^.def:=paraloc^.def;
  401. if firstparaloc then
  402. callpara^.alignment:=paras[i]^.Alignment
  403. else
  404. callpara^.alignment:=std_param_align;
  405. { if the paraloc doesn't contain the value itself, it's a byval
  406. parameter }
  407. if paraloc^.retvalloc then
  408. begin
  409. callpara^.sret:=true;
  410. callpara^.byval:=false;
  411. end
  412. else
  413. begin
  414. callpara^.sret:=false;
  415. callpara^.byval:=not paraloc^.llvmvalueloc;
  416. end;
  417. llvmextractvalueextinfo(paras[i]^.def, callpara^.def, callpara^.valueext);
  418. case paraloc^.llvmloc.loc of
  419. LOC_CONSTANT:
  420. begin
  421. callpara^.typ:=top_const;
  422. callpara^.value:=paraloc^.llvmloc.value;
  423. end;
  424. LOC_CREFERENCE:
  425. begin
  426. callpara^.typ:=top_ref;
  427. callpara^.sym:=paraloc^.llvmloc.sym;
  428. end
  429. else
  430. begin
  431. case paraloc^.loc of
  432. LOC_REFERENCE:
  433. begin
  434. if paraloc^.llvmvalueloc then
  435. internalerror(2014012307)
  436. else
  437. begin
  438. callpara^.typ:=top_reg;
  439. reference_reset_base(href, cpointerdef.getreusable(callpara^.def), paraloc^.reference.index, paraloc^.reference.offset, ctempposinvalid, paraloc^.def.alignment, []);
  440. res:=getregisterfordef(list, paraloc^.def);
  441. load_ref_anyreg(callpara^.def, href, res);
  442. end;
  443. callpara^.register:=res
  444. end;
  445. LOC_REGISTER,
  446. LOC_FPUREGISTER,
  447. LOC_MMREGISTER:
  448. begin
  449. callpara^.typ:=top_reg;
  450. { undo explicit value extension }
  451. if callpara^.valueext<>lve_none then
  452. begin
  453. res:=getregisterfordef(list, callpara^.def);
  454. a_load_reg_reg(list, paraloc^.def, callpara^.def, paraloc^.register, res);
  455. paraloc^.register:=res;
  456. end;
  457. callpara^.register:=paraloc^.register
  458. end;
  459. { empty records }
  460. LOC_VOID:
  461. begin
  462. callpara^.typ:=top_undef;
  463. end
  464. else
  465. internalerror(2014010605);
  466. end;
  467. end;
  468. end;
  469. callparas.add(callpara);
  470. paraloc:=paraloc^.next;
  471. firstparaloc:=false;
  472. end;
  473. end;
  474. { the Pascal level may expect a different returndef compared to the
  475. declared one }
  476. if pd.generate_safecall_wrapper then
  477. begin
  478. hlretdef:=ossinttype;
  479. llvmretdef:=ossinttype;
  480. end
  481. else
  482. begin
  483. if not assigned(forceresdef) then
  484. hlretdef:=pd.returndef
  485. else
  486. hlretdef:=forceresdef;
  487. { llvm will always expect the original return def }
  488. if not paramanager.ret_in_param(hlretdef, pd) or
  489. pd.generate_safecall_wrapper then
  490. llvmretdef:=llvmgetcgparadef(pd.funcretloc[callerside], true, callerside)
  491. else
  492. llvmretdef:=voidtype;
  493. end;
  494. if not is_void(llvmretdef) then
  495. res:=getregisterfordef(list, llvmretdef)
  496. else
  497. res:=NR_NO;
  498. { if this is a complex procvar, get the non-tmethod-like equivalent }
  499. if (pd.typ=procvardef) and
  500. not pd.is_addressonly then
  501. pd:=tprocvardef(cprocvardef.getreusableprocaddr(pd));
  502. end;
  503. function thlcgllvm.a_call_name(list: TAsmList; pd: tprocdef; const s: TSymStr; const paras: array of pcgpara; forceresdef: tdef; weak: boolean): tcgpara;
  504. var
  505. callparas: tfplist;
  506. llvmretdef,
  507. hlretdef: tdef;
  508. res: tregister;
  509. nextinslab,
  510. exceptlab: TAsmLabel;
  511. begin
  512. a_call_common(list,pd,paras,forceresdef,res,hlretdef,llvmretdef,callparas);
  513. if not(fc_catching_exceptions in flowcontrol) or
  514. { no invoke for intrinsics }
  515. (copy(s,1,5)='llvm.') then
  516. list.concat(taillvm.call_size_name_paras(get_call_pd(pd),pd.proccalloption,res,llvmretdef,current_asmdata.RefAsmSymbol(s,AT_FUNCTION),callparas))
  517. else
  518. begin
  519. current_asmdata.getjumplabel(nextinslab);
  520. exceptlab:=tllvmprocinfo(current_procinfo).CurrExceptLabel;
  521. list.concat(taillvm.invoke_size_name_paras_retlab_exceptlab(get_call_pd(pd),pd.proccalloption,res,llvmretdef,current_asmdata.RefAsmSymbol(s,AT_FUNCTION),callparas,nextinslab,exceptlab));
  522. a_label(list,nextinslab);
  523. end;
  524. result:=get_call_result_cgpara(pd,forceresdef);
  525. set_call_function_result(list,pd,llvmretdef,hlretdef,res,result);
  526. end;
  527. function thlcgllvm.a_call_reg(list: TAsmList; pd: tabstractprocdef; reg: tregister; const paras: array of pcgpara): tcgpara;
  528. var
  529. callparas: tfplist;
  530. llvmretdef,
  531. hlretdef: tdef;
  532. res: tregister;
  533. nextinslab,
  534. exceptlab: TAsmLabel;
  535. begin
  536. a_call_common(list,pd,paras,nil,res,hlretdef,llvmretdef,callparas);
  537. if not(fc_catching_exceptions in flowcontrol) then
  538. list.concat(taillvm.call_size_reg_paras(get_call_pd(pd),pd.proccalloption,res,llvmretdef,reg,callparas))
  539. else
  540. begin
  541. current_asmdata.getjumplabel(nextinslab);
  542. exceptlab:=tllvmprocinfo(current_procinfo).CurrExceptLabel;
  543. list.concat(taillvm.invoke_size_reg_paras_retlab_exceptlab(get_call_pd(pd),pd.proccalloption,res,llvmretdef,reg,callparas,nextinslab,exceptlab));
  544. a_label(list,nextinslab);
  545. end;
  546. result:=get_call_result_cgpara(pd,nil);
  547. set_call_function_result(list,pd,llvmretdef,hlretdef,res,result);
  548. end;
  549. procedure thlcgllvm.a_load_const_reg(list: TAsmList; tosize: tdef; a: tcgint; register: tregister);
  550. var
  551. fromsize: tdef;
  552. begin
  553. if tosize=llvm_metadatatype then
  554. internalerror(2019122804);
  555. if tosize.size<=ptrsinttype.size then
  556. fromsize:=ptrsinttype
  557. else
  558. fromsize:=tosize;
  559. list.concat(taillvm.op_reg_size_const_size(llvmconvop(fromsize,tosize,false),register,fromsize,a,tosize))
  560. end;
  561. procedure thlcgllvm.a_load_const_ref(list: TAsmList; tosize: tdef; a: tcgint; const ref: treference);
  562. var
  563. sref: treference;
  564. begin
  565. { llvm instructions do not support pointer constants -> only directly
  566. encode for integers; a_load_const_reg() handles pointers properly }
  567. if is_ordinal(tosize) or
  568. is_64bit(tosize) then
  569. begin
  570. sref:=make_simple_ref(list,ref,tosize);
  571. list.concat(taillvm.op_size_const_size_ref(la_store,tosize,a,cpointerdef.getreusable(tosize),sref))
  572. end
  573. else
  574. inherited;
  575. end;
  576. function def2intdef(fromsize, tosize: tdef): tdef;
  577. begin
  578. { we cannot zero-extend from/to anything but ordinal/enum
  579. types }
  580. if not(tosize.typ in [orddef,enumdef]) then
  581. internalerror(2014012305);
  582. { will give an internalerror if def_cgsize() returns OS_NO, which is
  583. what we want }
  584. result:=cgsize_orddef(def_cgsize(fromsize));
  585. end;
  586. procedure thlcgllvm.a_load_reg_ref(list: TAsmList; fromsize, tosize: tdef; register: tregister; const ref: treference);
  587. var
  588. tmpref,
  589. sref: treference;
  590. hreg,
  591. hreg2: tregister;
  592. tmpsize: tdef;
  593. begin
  594. if (fromsize=llvm_metadatatype) or
  595. (tosize=llvm_metadatatype) then
  596. internalerror(2019122802);
  597. sref:=make_simple_ref(list,ref,tosize);
  598. hreg:=register;
  599. (* typecast the pointer to the value instead of the value itself if
  600. they have the same size but are of different kinds, because we can't
  601. e.g. typecast a loaded <{i32, i32}> to an i64 *)
  602. if (llvmaggregatetype(fromsize) or
  603. llvmaggregatetype(tosize)) and
  604. (fromsize<>tosize) then
  605. begin
  606. if fromsize.size>tosize.size then
  607. begin
  608. { if source size is larger than the target size, we have to
  609. truncate it before storing. Unfortunately, we cannot truncate
  610. records (nor bitcast them to integers), so we first have to
  611. store them to memory and then bitcast the pointer to them
  612. We can't truncate an integer to 3/5/6/7 bytes either, so also
  613. pass via a temp in that case
  614. }
  615. if (fromsize.typ in [arraydef,recorddef]) or
  616. (tosize.size in [3,5,6,7]) then
  617. begin
  618. { store struct/array-in-register to memory }
  619. tg.gethltemp(list,fromsize,fromsize.size,tt_normal,tmpref);
  620. a_load_reg_ref(list,fromsize,fromsize,register,tmpref);
  621. { typecast pointer to memory into pointer to integer type }
  622. hreg:=getaddressregister(list,cpointerdef.getreusable(tosize));
  623. a_loadaddr_ref_reg(list,fromsize,cpointerdef.getreusable(tosize),tmpref,hreg);
  624. reference_reset_base(sref,cpointerdef.getreusable(tosize),hreg,0,tmpref.temppos,tmpref.alignment,tmpref.volatility);
  625. { load the integer from the temp into the destination }
  626. a_load_ref_ref(list,tosize,tosize,sref,ref);
  627. tg.ungettemp(list,tmpref);
  628. end
  629. else
  630. begin
  631. tmpsize:=def2intdef(tosize,fromsize);
  632. hreg:=getintregister(list,tmpsize);
  633. { truncate the integer }
  634. a_load_reg_reg(list,fromsize,tmpsize,register,hreg);
  635. { store it to memory (it will now be of the same size as the
  636. struct, and hence another path will be followed in this
  637. method) }
  638. a_load_reg_ref(list,tmpsize,tosize,hreg,sref);
  639. end;
  640. exit;
  641. end
  642. else
  643. begin
  644. hreg2:=getaddressregister(list,cpointerdef.getreusable(fromsize));
  645. a_loadaddr_ref_reg(list,tosize,cpointerdef.getreusable(fromsize),sref,hreg2);
  646. reference_reset_base(sref,cpointerdef.getreusable(fromsize),hreg2,0,sref.temppos,sref.alignment,sref.volatility);
  647. tosize:=fromsize;
  648. end;
  649. end
  650. else if fromsize<>tosize then
  651. begin
  652. hreg:=getregisterfordef(list,tosize);
  653. a_load_reg_reg(list,fromsize,tosize,register,hreg);
  654. end;
  655. list.concat(taillvm.op_size_reg_size_ref(la_store,tosize,hreg,cpointerdef.getreusable(tosize),sref));
  656. end;
  657. procedure thlcgllvm.a_load_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister);
  658. var
  659. op: tllvmop;
  660. tmpreg: tregister;
  661. tmpintdef: tdef;
  662. begin
  663. if (fromsize=llvm_metadatatype) or
  664. (tosize=llvm_metadatatype) then
  665. internalerror(2019122801);
  666. op:=llvmconvop(fromsize,tosize,true);
  667. { converting from pointer to something else and vice versa is only
  668. possible via an intermediate pass to integer. Same for "something else"
  669. to pointer. }
  670. case op of
  671. la_ptrtoint_to_x,
  672. la_x_to_inttoptr:
  673. begin
  674. { convert via an integer with the same size as "x" }
  675. if op=la_ptrtoint_to_x then
  676. begin
  677. tmpintdef:=cgsize_orddef(def_cgsize(tosize));
  678. op:=la_bitcast
  679. end
  680. else
  681. begin
  682. tmpintdef:=cgsize_orddef(def_cgsize(fromsize));
  683. op:=la_inttoptr;
  684. end;
  685. tmpreg:=getintregister(list,tmpintdef);
  686. a_load_reg_reg(list,fromsize,tmpintdef,reg1,tmpreg);
  687. reg1:=tmpreg;
  688. fromsize:=tmpintdef;
  689. end;
  690. else
  691. ;
  692. end;
  693. { reg2 = bitcast fromsize reg1 to tosize }
  694. list.concat(taillvm.op_reg_size_reg_size(op,reg2,fromsize,reg1,tosize));
  695. end;
  696. procedure thlcgllvm.gen_load_refaddrfull_anyreg(list: TAsmList; fromsize, tosize: tdef; const simpleref: treference; register: tregister; shuffle: pmmshuffle);
  697. var
  698. tmpref,
  699. tmpref2: treference;
  700. begin
  701. { can't bitcast records/arrays }
  702. if (llvmaggregatetype(fromsize) or
  703. llvmaggregatetype(tosize)) and
  704. (fromsize<>tosize) then
  705. begin
  706. if fromsize.size>tosize.size then
  707. begin
  708. tg.gethltemp(list,fromsize,fromsize.size,tt_normal,tmpref);
  709. tmpref2:=tmpref;
  710. g_ptrtypecast_ref(list,cpointerdef.getreusable(fromsize),cpointerdef.getreusable(tosize),tmpref2);
  711. end
  712. else
  713. begin
  714. tg.gethltemp(list,tosize,tosize.size,tt_normal,tmpref);
  715. tmpref2:=tmpref;
  716. g_ptrtypecast_ref(list,cpointerdef.getreusable(tosize),cpointerdef.getreusable(fromsize),tmpref);
  717. end;
  718. list.concat(taillvm.op_size_ref_size_ref(la_store,fromsize,simpleref,cpointerdef.getreusable(fromsize),tmpref));
  719. case getregtype(register) of
  720. R_INTREGISTER,
  721. R_ADDRESSREGISTER:
  722. a_load_ref_reg(list,tosize,tosize,tmpref2,register);
  723. R_FPUREGISTER:
  724. a_loadfpu_ref_reg(list,tosize,tosize,tmpref2,register);
  725. R_MMREGISTER:
  726. a_loadmm_ref_reg(list,tosize,tosize,tmpref2,register,shuffle);
  727. else
  728. internalerror(2016061901);
  729. end;
  730. tg.ungettemp(list,tmpref);
  731. end
  732. else
  733. list.concat(taillvm.op_reg_size_ref_size(llvmconvop(fromsize,tosize,false),register,fromsize,simpleref,tosize))
  734. end;
  735. function thlcgllvm.handle_agg_load_ref_anyreg(list: TasmList; var fromsize, tosize: tdef; var simpleref: treference; register: tregister; shuffle: pmmshuffle): boolean;
  736. var
  737. tmpref,
  738. tmpref2: treference;
  739. firstshuffle: pmmshuffle;
  740. begin
  741. if fromsize.size<tosize.size then
  742. begin
  743. { allocate a temp of size tosize, typecast it to the
  744. (smaller) fromsize, load the source in it, and then
  745. load the destination from it. The extra bits will contain
  746. garbage, but they should never be used. }
  747. tg.gethltemp(list,tosize,tosize.size,tt_persistent,tmpref);
  748. tmpref2:=tmpref;
  749. g_ptrtypecast_ref(list,cpointerdef.getreusable(tosize),cpointerdef.getreusable(fromsize),tmpref2);
  750. case getregtype(register) of
  751. R_INTREGISTER,
  752. R_ADDRESSREGISTER:
  753. begin
  754. a_load_ref_ref(list,fromsize,fromsize,simpleref,tmpref2);
  755. a_load_ref_reg(list,tosize,tosize,tmpref,register);
  756. end;
  757. R_FPUREGISTER:
  758. begin
  759. a_loadfpu_ref_ref(list,fromsize,fromsize,simpleref,tmpref2);
  760. a_loadfpu_ref_reg(list,tosize,tosize,tmpref,register);
  761. end;
  762. R_MMREGISTER:
  763. begin
  764. { don't shuffle twice }
  765. if shuffle=mms_movescalar then
  766. firstshuffle:=shuffle
  767. else
  768. firstshuffle:=nil;
  769. a_loadmm_ref_ref(list,fromsize,fromsize,simpleref,tmpref2,firstshuffle);
  770. a_loadmm_ref_reg(list,tosize,tosize,tmpref,register,shuffle);
  771. end;
  772. else
  773. internalerror(2019051040);
  774. end;
  775. tg.ungettemp(list,tmpref);
  776. result:=true;
  777. end
  778. else
  779. begin
  780. (* typecast the pointer to the value instead of the value
  781. itself if tosize<=fromsize but they are of different
  782. kinds, because we can't e.g. bitcast a loaded <{i32, i32}>
  783. to an i64 *)
  784. g_ptrtypecast_ref(list,cpointerdef.getreusable(fromsize),cpointerdef.getreusable(tosize),simpleref);
  785. fromsize:=tosize;
  786. result:=false;
  787. end;
  788. end;
  789. procedure thlcgllvm.a_load_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; register: tregister);
  790. var
  791. sref: treference;
  792. hreg: tregister;
  793. begin
  794. if (fromsize=llvm_metadatatype) or
  795. (tosize=llvm_metadatatype) then
  796. internalerror(2019122803);
  797. sref:=make_simple_ref(list,ref,fromsize);
  798. { "named register"? }
  799. if sref.refaddr=addr_full then
  800. gen_load_refaddrfull_anyreg(list,fromsize,tosize,sref,register,nil)
  801. else
  802. begin
  803. if ((fromsize.typ in [arraydef,recorddef]) or
  804. (tosize.typ in [arraydef,recorddef])) and
  805. (fromsize<>tosize) then
  806. begin
  807. if handle_agg_load_ref_anyreg(list,fromsize,tosize,sref,register,nil) then
  808. exit;
  809. end;
  810. hreg:=register;
  811. if fromsize<>tosize then
  812. hreg:=getregisterfordef(list,fromsize);
  813. list.concat(taillvm.op_reg_size_ref(la_load,hreg,cpointerdef.getreusable(fromsize),sref));
  814. if hreg<>register then
  815. a_load_reg_reg(list,fromsize,tosize,hreg,register);
  816. end;
  817. end;
  818. procedure thlcgllvm.a_load_ref_ref(list: TAsmList; fromsize, tosize: tdef; const sref: treference; const dref: treference);
  819. var
  820. sdref: treference;
  821. begin
  822. if (fromsize=tosize) and
  823. (sref.refaddr=addr_full) then
  824. begin
  825. sdref:=make_simple_ref(list,dref,tosize);
  826. list.concat(taillvm.op_size_ref_size_ref(la_store,fromsize,sref,cpointerdef.getreusable(tosize),sdref));
  827. end
  828. else if (fromsize=tosize) and
  829. not(fromsize.typ in [orddef,floatdef,enumdef]) and
  830. (sref.refaddr<>addr_full) and
  831. (fromsize.size>2*sizeof(aint)) then
  832. g_concatcopy(list,fromsize,sref,dref)
  833. else
  834. inherited
  835. end;
  836. procedure thlcgllvm.a_loadaddr_ref_reg_intern(list: TAsmList; fromsize, tosize: tdef; const ref: treference; r: tregister; makefromsizepointer: boolean);
  837. var
  838. sref: treference;
  839. begin
  840. { can't take the address of a 'named register' }
  841. if ref.refaddr=addr_full then
  842. internalerror(2013102306);
  843. if makefromsizepointer then
  844. fromsize:=cpointerdef.getreusable(fromsize);
  845. sref:=make_simple_ref_ptr(list,ref,fromsize);
  846. list.concat(taillvm.op_reg_size_ref_size(la_bitcast,r,fromsize,sref,tosize));
  847. end;
  848. procedure thlcgllvm.a_loadaddr_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; r: tregister);
  849. begin
  850. a_loadaddr_ref_reg_intern(list,fromsize,tosize,ref,r,true);
  851. end;
  852. procedure thlcgllvm.a_op_const_reg(list: TAsmList; Op: TOpCG; size: tdef; a: tcgint; reg: TRegister);
  853. begin
  854. a_op_const_reg_reg(list,op,size,a,reg,reg);
  855. end;
  856. procedure thlcgllvm.a_op_const_reg_reg(list: TAsmList; op: TOpCg; size: tdef; a: tcgint; src, dst: tregister);
  857. var
  858. tmpreg: tregister;
  859. begin
  860. if (def2regtyp(size)=R_INTREGISTER) and
  861. (topcg2llvmop[op]<>la_none) then
  862. list.concat(taillvm.op_reg_size_reg_const(topcg2llvmop[op],dst,size,src,a))
  863. else
  864. begin
  865. { default implementation is not SSA-safe }
  866. tmpreg:=getregisterfordef(list,size);
  867. a_load_const_reg(list,size,a,tmpreg);
  868. a_op_reg_reg_reg(list,op,size,tmpreg,src,dst);
  869. end;
  870. end;
  871. procedure thlcgllvm.a_op_reg_reg_reg(list: TAsmList; op: TOpCg; size: tdef; src1, src2, dst: tregister);
  872. var
  873. orgdst,
  874. tmpreg1,
  875. tmpreg2,
  876. tmpreg3: tregister;
  877. opsize: tdef;
  878. begin
  879. orgdst:=dst;
  880. opsize:=size;
  881. { always perform using integer registers, because math operations on
  882. pointers are not supported (except via getelementptr, possible future
  883. optimization) }
  884. if def2regtyp(size)=R_ADDRESSREGISTER then
  885. begin
  886. opsize:=ptruinttype;
  887. tmpreg1:=getintregister(list,ptruinttype);
  888. a_load_reg_reg(list,size,ptruinttype,src1,tmpreg1);
  889. src1:=tmpreg1;
  890. tmpreg1:=getintregister(list,ptruinttype);
  891. a_load_reg_reg(list,size,ptruinttype,src2,tmpreg1);
  892. src2:=tmpreg1;
  893. dst:=getintregister(list,ptruinttype);
  894. end;
  895. if topcg2llvmop[op]<>la_none then
  896. list.concat(taillvm.op_reg_size_reg_reg(topcg2llvmop[op],dst,opsize,src2,src1))
  897. else
  898. begin
  899. case op of
  900. OP_NEG:
  901. { %dst = sub size 0, %src1 }
  902. list.concat(taillvm.op_reg_size_const_reg(la_sub,dst,opsize,0,src1));
  903. OP_NOT:
  904. { %dst = xor size -1, %src1 }
  905. list.concat(taillvm.op_reg_size_const_reg(la_xor,dst,opsize,-1,src1));
  906. OP_ROL:
  907. begin
  908. tmpreg1:=getintregister(list,opsize);
  909. tmpreg2:=getintregister(list,opsize);
  910. tmpreg3:=getintregister(list,opsize);
  911. { tmpreg1 := (tcgsize2size[size]*8 - (src1 and (tcgsize2size[size]*8-1) }
  912. list.concat(taillvm.op_reg_size_const_reg(la_and,tmpreg1,opsize,opsize.size*8-1,src1));
  913. list.concat(taillvm.op_reg_size_const_reg(la_sub,tmpreg2,opsize,opsize.size*8,tmpreg1));
  914. { tmpreg3 := src2 shr tmpreg2 }
  915. a_op_reg_reg_reg(list,OP_SHR,opsize,tmpreg2,src2,tmpreg3);
  916. { tmpreg2:= src2 shl tmpreg1 }
  917. tmpreg2:=getintregister(list,opsize);
  918. a_op_reg_reg_reg(list,OP_SHL,opsize,tmpreg1,src2,tmpreg2);
  919. { dst := tmpreg2 or tmpreg3 }
  920. a_op_reg_reg_reg(list,OP_OR,opsize,tmpreg2,tmpreg3,dst);
  921. end;
  922. OP_ROR:
  923. begin
  924. tmpreg1:=getintregister(list,size);
  925. tmpreg2:=getintregister(list,size);
  926. tmpreg3:=getintregister(list,size);
  927. { tmpreg1 := (tcgsize2size[size]*8 - (src1 and (tcgsize2size[size]*8-1) }
  928. list.concat(taillvm.op_reg_size_const_reg(la_and,tmpreg1,opsize,opsize.size*8-1,src1));
  929. list.concat(taillvm.op_reg_size_const_reg(la_sub,tmpreg2,opsize,opsize.size*8,tmpreg1));
  930. { tmpreg3 := src2 shl tmpreg2 }
  931. a_op_reg_reg_reg(list,OP_SHL,opsize,tmpreg2,src2,tmpreg3);
  932. { tmpreg2:= src2 shr tmpreg1 }
  933. tmpreg2:=getintregister(list,opsize);
  934. a_op_reg_reg_reg(list,OP_SHR,opsize,tmpreg1,src2,tmpreg2);
  935. { dst := tmpreg2 or tmpreg3 }
  936. a_op_reg_reg_reg(list,OP_OR,opsize,tmpreg2,tmpreg3,dst);
  937. end;
  938. else
  939. internalerror(2010081310);
  940. end;
  941. end;
  942. if dst<>orgdst then
  943. a_load_reg_reg(list,opsize,size,dst,orgdst);
  944. end;
  945. procedure thlcgllvm.a_op_reg_reg(list: TAsmList; Op: TOpCG; size: tdef; reg1, reg2: TRegister);
  946. begin
  947. a_op_reg_reg_reg(list,op,size,reg1,reg2,reg2);
  948. end;
  949. procedure thlcgllvm.a_op_const_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tdef; a: tcgint; src, dst: tregister; setflags: boolean; var ovloc: tlocation);
  950. var
  951. hreg: tregister;
  952. begin
  953. if not setflags then
  954. begin
  955. inherited;
  956. exit;
  957. end;
  958. hreg:=getintregister(list,size);
  959. a_load_const_reg(list,size,a,hreg);
  960. a_op_reg_reg_reg_checkoverflow(list,op,size,hreg,src,dst,setflags,ovloc);
  961. end;
  962. procedure thlcgllvm.a_op_reg_reg_reg_checkoverflow(list: TAsmList; op: TOpCg; size: tdef; src1, src2, dst: tregister; setflags: boolean; var ovloc: tlocation);
  963. var
  964. calcsize: tdef;
  965. tmpsrc1,
  966. tmpsrc2,
  967. tmpdst: tregister;
  968. signed,
  969. docheck: boolean;
  970. begin
  971. docheck:=size.size>=ossinttype.size;
  972. if not setflags or
  973. not docheck then
  974. begin
  975. inherited a_op_reg_reg_reg_checkoverflow(list,op,size,src1,src2,dst,false,ovloc);
  976. exit;
  977. end;
  978. { extend values to twice their original width (one bit extra is enough,
  979. but adding support for 9/17/33/65 bit types just for this is overkill) }
  980. signed:=is_signed(size);
  981. case size.size of
  982. 1:
  983. if signed then
  984. calcsize:=s16inttype
  985. else
  986. calcsize:=u16inttype;
  987. 2:
  988. if signed then
  989. calcsize:=s32inttype
  990. else
  991. calcsize:=u32inttype;
  992. 4:
  993. if signed then
  994. calcsize:=s64inttype
  995. else
  996. calcsize:=u64inttype;
  997. 8:
  998. if signed then
  999. calcsize:=s128inttype
  1000. else
  1001. calcsize:=u128inttype;
  1002. else
  1003. internalerror(2015122503);
  1004. end;
  1005. tmpsrc1:=getintregister(list,calcsize);
  1006. a_load_reg_reg(list,size,calcsize,src1,tmpsrc1);
  1007. tmpsrc2:=getintregister(list,calcsize);
  1008. a_load_reg_reg(list,size,calcsize,src2,tmpsrc2);
  1009. tmpdst:=getintregister(list,calcsize);
  1010. { perform the calculation with twice the width }
  1011. a_op_reg_reg_reg(list,op,calcsize,tmpsrc1,tmpsrc2,tmpdst);
  1012. { signed/unsigned overflow occurs if signed/unsigned truncation of the
  1013. result is different from the actual result -> extend again and compare }
  1014. a_load_reg_reg(list,calcsize,size,tmpdst,dst);
  1015. tmpsrc1:=getintregister(list,calcsize);
  1016. a_load_reg_reg(list,size,calcsize,dst,tmpsrc1);
  1017. location_reset(ovloc,LOC_REGISTER,OS_8);
  1018. ovloc.register:=getintregister(list,llvmbool1type);
  1019. list.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp,ovloc.register,OC_NE,calcsize,tmpsrc1,tmpdst));
  1020. end;
  1021. procedure thlcgllvm.a_cmp_const_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; a: tcgint; reg: tregister; l: tasmlabel);
  1022. var
  1023. tmpreg : tregister;
  1024. invert: boolean;
  1025. fallthroughlab, falselab, tmplab: tasmlabel;
  1026. begin
  1027. tmpreg:=getregisterfordef(list,size);
  1028. a_load_const_reg(list,size,a,tmpreg);
  1029. a_cmp_reg_reg_label(list,size,cmp_op,tmpreg,reg,l);
  1030. end;
  1031. procedure thlcgllvm.a_cmp_reg_reg_label(list: TAsmList; size: tdef; cmp_op: topcmp; reg1, reg2: tregister; l: tasmlabel);
  1032. var
  1033. resreg: tregister;
  1034. falselab: tasmlabel;
  1035. begin
  1036. if getregtype(reg1)<>getregtype(reg2) then
  1037. internalerror(2012111105);
  1038. resreg:=getintregister(list,llvmbool1type);
  1039. current_asmdata.getjumplabel(falselab);
  1040. { invert order of registers. In FPC, cmp_reg_reg(reg1,reg2) means that
  1041. e.g. OC_GT is true if "subl %reg1,%reg2" in x86 AT&T is >0. In LLVM,
  1042. OC_GT is true if op1>op2 }
  1043. list.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp,resreg,cmp_op,size,reg2,reg1));
  1044. list.concat(taillvm.op_size_reg_lab_lab(la_br,llvmbool1type,resreg,l,falselab));
  1045. a_label(list,falselab);
  1046. end;
  1047. procedure thlcgllvm.a_jmp_always(list: TAsmList; l: tasmlabel);
  1048. begin
  1049. { implement in tcg because required by the overridden a_label; doesn't use
  1050. any high level stuff anyway }
  1051. cg.a_jmp_always(list,l);
  1052. end;
  1053. procedure thlcgllvm.g_unreachable(list: TAsmList);
  1054. begin
  1055. list.Concat(taillvm.op_none(la_unreachable));
  1056. end;
  1057. procedure thlcgllvm.g_concatcopy(list: TAsmList; size: tdef; const source, dest: treference);
  1058. var
  1059. pd: tprocdef;
  1060. sourcepara, destpara, sizepara, alignpara, volatilepara: tcgpara;
  1061. maxalign: longint;
  1062. indivalign: boolean;
  1063. begin
  1064. { perform small copies directly; not larger ones, because then llvm
  1065. will try to load the entire large datastructure into registers and
  1066. starts spilling like crazy; too small copies must not be done via
  1067. llvm.memcpy either, because then you get crashes in llvm }
  1068. if (size.typ in [orddef,floatdef,enumdef]) or
  1069. (size.size<=2*sizeof(aint)) then
  1070. begin
  1071. a_load_ref_ref(list,size,size,source,dest);
  1072. exit;
  1073. end;
  1074. indivalign:=llvmflag_memcpy_indiv_align in llvmversion_properties[current_settings.llvmversion];
  1075. if indivalign then
  1076. pd:=search_system_proc('llvm_memcpy64_indivalign')
  1077. else
  1078. pd:=search_system_proc('llvm_memcpy64');
  1079. sourcepara.init;
  1080. destpara.init;
  1081. sizepara.init;
  1082. alignpara.init;
  1083. volatilepara.init;
  1084. paramanager.getcgtempparaloc(list,pd,1,destpara);
  1085. paramanager.getcgtempparaloc(list,pd,2,sourcepara);
  1086. paramanager.getcgtempparaloc(list,pd,3,sizepara);
  1087. if indivalign then
  1088. begin
  1089. paramanager.getcgtempparaloc(list,pd,4,volatilepara);
  1090. destpara.Alignment:=-dest.alignment;
  1091. sourcepara.Alignment:=-source.alignment;
  1092. end
  1093. else
  1094. begin
  1095. paramanager.getcgtempparaloc(list,pd,4,alignpara);
  1096. paramanager.getcgtempparaloc(list,pd,5,volatilepara);
  1097. maxalign:=newalignment(max(source.alignment,dest.alignment),min(source.alignment,dest.alignment));
  1098. a_load_const_cgpara(list,u32inttype,maxalign,alignpara);
  1099. end;
  1100. a_loadaddr_ref_cgpara(list,size,dest,destpara);
  1101. a_loadaddr_ref_cgpara(list,size,source,sourcepara);
  1102. a_load_const_cgpara(list,u64inttype,size.size,sizepara);
  1103. a_load_const_cgpara(list,llvmbool1type,ord((vol_read in source.volatility) or (vol_write in dest.volatility)),volatilepara);
  1104. if indivalign then
  1105. g_call_system_proc(list,pd,[@destpara,@sourcepara,@sizepara,@volatilepara],nil).resetiftemp
  1106. else
  1107. g_call_system_proc(list,pd,[@destpara,@sourcepara,@sizepara,@alignpara,@volatilepara],nil).resetiftemp;
  1108. sourcepara.done;
  1109. destpara.done;
  1110. sizepara.done;
  1111. alignpara.done;
  1112. volatilepara.done;
  1113. end;
  1114. procedure thlcgllvm.a_loadfpu_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister);
  1115. var
  1116. tmpreg: tregister;
  1117. href: treference;
  1118. fromcompcurr,
  1119. tocompcurr: boolean;
  1120. begin
  1121. href:=make_simple_ref(list,ref,fromsize);
  1122. { named register -> use generic code }
  1123. if ref.refaddr=addr_full then
  1124. begin
  1125. gen_load_refaddrfull_anyreg(list,fromsize,tosize,href,reg,mms_movescalar);
  1126. exit
  1127. end;
  1128. { comp and currency are handled by the x87 in this case. They cannot
  1129. be represented directly in llvm, and llvmdef translates them into i64
  1130. (since that's their storage size and internally they also are int64).
  1131. Solve this by changing the type to s80real once they are loaded into
  1132. a register. }
  1133. fromcompcurr:=
  1134. (fromsize.typ=floatdef) and
  1135. (tfloatdef(fromsize).floattype in [s64comp,s64currency]);
  1136. tocompcurr:=
  1137. (tosize.typ=floatdef) and
  1138. (tfloatdef(tosize).floattype in [s64comp,s64currency]);
  1139. if tocompcurr then
  1140. tosize:=s80floattype;
  1141. { don't generate different code for loading e.g. extended into cextended,
  1142. but to take care of loading e.g. comp (=int64) into double }
  1143. if (fromsize.size<>tosize.size) then
  1144. tmpreg:=getfpuregister(list,fromsize)
  1145. else
  1146. tmpreg:=reg;
  1147. { handle aggregate loads (happens if a struct needs to be passed in a
  1148. floating point register) }
  1149. if (fromsize.typ in [arraydef,recorddef]) or
  1150. (tosize.typ in [arraydef,recorddef]) then
  1151. begin
  1152. if handle_agg_load_ref_anyreg(list,fromsize,tosize,href,reg,mms_movescalar) then
  1153. exit;
  1154. end;
  1155. { %tmpreg = load size* %ref }
  1156. list.concat(taillvm.op_reg_size_ref(la_load,tmpreg,cpointerdef.getreusable(fromsize),href));
  1157. if tmpreg<>reg then
  1158. if fromcompcurr then
  1159. { treat as extended as long as it's in a register }
  1160. list.concat(taillvm.op_reg_size_reg_size(la_sitofp,reg,fromsize,tmpreg,tosize))
  1161. else
  1162. a_loadfpu_reg_reg(list,fromsize,tosize,tmpreg,reg);
  1163. end;
  1164. procedure thlcgllvm.a_loadfpu_reg_ref(list: TAsmList; fromsize, tosize: tdef; reg: tregister; const ref: treference);
  1165. var
  1166. tmpreg: tregister;
  1167. href: treference;
  1168. fromcompcurr,
  1169. tocompcurr: boolean;
  1170. begin
  1171. { see comment in a_loadfpu_ref_reg }
  1172. fromcompcurr:=
  1173. (fromsize.typ=floatdef) and
  1174. (tfloatdef(fromsize).floattype in [s64comp,s64currency]);
  1175. tocompcurr:=
  1176. (tosize.typ=floatdef) and
  1177. (tfloatdef(tosize).floattype in [s64comp,s64currency]);
  1178. if fromcompcurr then
  1179. fromsize:=s80floattype;
  1180. href:=make_simple_ref(list,ref,tosize);
  1181. { don't generate different code for loading e.g. extended into cextended,
  1182. but to take care of storing e.g. comp (=int64) into double }
  1183. if (fromsize.size<>tosize.size) then
  1184. begin
  1185. tmpreg:=getfpuregister(list,tosize);
  1186. if tocompcurr then
  1187. { store back an int64 rather than an extended }
  1188. list.concat(taillvm.op_reg_size_reg_size(la_fptosi,tmpreg,fromsize,reg,tosize))
  1189. else
  1190. a_loadfpu_reg_reg(list,fromsize,tosize,reg,tmpreg);
  1191. end
  1192. else
  1193. tmpreg:=reg;
  1194. { store tosize tmpreg, tosize* href }
  1195. list.concat(taillvm.op_size_reg_size_ref(la_store,tosize,tmpreg,cpointerdef.getreusable(tosize),href));
  1196. end;
  1197. procedure thlcgllvm.a_loadfpu_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister);
  1198. var
  1199. op: tllvmop;
  1200. begin
  1201. op:=llvmconvop(fromsize,tosize,true);
  1202. { reg2 = bitcast fromllsize reg1 to tollsize }
  1203. list.concat(taillvm.op_reg_size_reg_size(op,reg2,fromsize,reg1,tosize));
  1204. end;
  1205. procedure thlcgllvm.gen_proc_symbol(list: TAsmList);
  1206. var
  1207. item: TCmdStrListItem;
  1208. mangledname: TSymStr;
  1209. asmsym: tasmsymbol;
  1210. begin
  1211. if po_external in current_procinfo.procdef.procoptions then
  1212. exit;
  1213. item:=TCmdStrListItem(current_procinfo.procdef.aliasnames.first);
  1214. mangledname:=current_procinfo.procdef.mangledname;
  1215. { predefine the real function name as local/global, so the aliases can
  1216. refer to the symbol and get the binding correct }
  1217. if (cs_profile in current_settings.moduleswitches) or
  1218. (po_global in current_procinfo.procdef.procoptions) then
  1219. asmsym:=current_asmdata.DefineAsmSymbol(mangledname,AB_GLOBAL,AT_FUNCTION,current_procinfo.procdef)
  1220. else
  1221. asmsym:=current_asmdata.DefineAsmSymbol(mangledname,AB_LOCAL,AT_FUNCTION,current_procinfo.procdef);
  1222. while assigned(item) do
  1223. begin
  1224. if mangledname<>item.Str then
  1225. list.concat(taillvmalias.create(asmsym,item.str,current_procinfo.procdef,asmsym.bind));
  1226. item:=TCmdStrListItem(item.next);
  1227. end;
  1228. list.concat(taillvmdecl.createdef(asmsym,current_procinfo.procdef,nil,sec_code,current_procinfo.procdef.alignment));
  1229. end;
  1230. procedure thlcgllvm.handle_external_proc(list: TAsmList; pd: tprocdef; const importname: TSymStr);
  1231. begin
  1232. { don't do anything, because at this point we can't know yet for certain
  1233. whether the aliased routine is internal to the current routine or not.
  1234. If it's internal, we would have to generate an llvm alias, while if it's
  1235. external, we would have to generate a declaration. Additionally, aliases
  1236. cannot refer to declarations, so always creating aliases doesn't work
  1237. either -> handle in llvmtype }
  1238. end;
  1239. procedure thlcgllvm.g_proc_entry(list: TAsmList; localsize: longint; nostackframe: boolean);
  1240. begin
  1241. list.concatlist(ttgllvm(tg).alloclist)
  1242. { rest: todo }
  1243. end;
  1244. procedure thlcgllvm.g_proc_exit(list: TAsmList; parasize: longint; nostackframe: boolean);
  1245. var
  1246. retdef: tdef;
  1247. retreg,
  1248. hreg: tregister;
  1249. retpara: tcgpara;
  1250. begin
  1251. { the function result type is the type of the first location, which can
  1252. differ from the real result type (e.g. int64 for a record consisting of
  1253. two longint fields on x86-64 -- we are responsible for lowering the
  1254. result types like that) }
  1255. retpara:=get_call_result_cgpara(current_procinfo.procdef,nil);
  1256. retpara.check_simple_location;
  1257. retdef:=retpara.location^.def;
  1258. if (is_void(retdef) or
  1259. { don't check retdef here, it is e.g. a pshortstring in case it's
  1260. shortstring that's returned in a parameter }
  1261. paramanager.ret_in_param(current_procinfo.procdef.returndef,current_procinfo.procdef)) and
  1262. not current_procinfo.procdef.generate_safecall_wrapper then
  1263. list.concat(taillvm.op_size(la_ret,voidtype))
  1264. else
  1265. begin
  1266. case retpara.location^.loc of
  1267. LOC_REGISTER,
  1268. LOC_FPUREGISTER,
  1269. LOC_MMREGISTER:
  1270. begin
  1271. { sign/zeroextension of function results is handled implicitly
  1272. via the signext/zeroext modifiers of the result, rather than
  1273. in the code generator -> remove any explicit extensions here }
  1274. retreg:=retpara.location^.register;
  1275. if (current_procinfo.procdef.returndef.typ in [orddef,enumdef]) and
  1276. (retdef.typ in [orddef,enumdef]) and
  1277. not current_procinfo.procdef.generate_safecall_wrapper then
  1278. begin
  1279. if (current_procinfo.procdef.returndef.size<retpara.location^.def.size) then
  1280. begin
  1281. hreg:=getintregister(list,current_procinfo.procdef.returndef);
  1282. a_load_reg_reg(list,retdef,current_procinfo.procdef.returndef,retreg,hreg);
  1283. retreg:=hreg;
  1284. retdef:=current_procinfo.procdef.returndef;
  1285. end;
  1286. end;
  1287. list.concat(taillvm.op_size_reg(la_ret,retdef,retreg))
  1288. end;
  1289. LOC_VOID:
  1290. begin
  1291. { zero-sized records: return an undefined zero-sized record of
  1292. the correct type }
  1293. list.concat(taillvm.op_size_undef(la_ret,retdef));
  1294. end
  1295. else
  1296. { todo: complex returns }
  1297. internalerror(2012111106);
  1298. end;
  1299. end;
  1300. retpara.resetiftemp;
  1301. end;
  1302. procedure thlcgllvm.gen_load_uninitialized_function_result(list: TAsmList; pd: tprocdef; resdef: tdef; const resloc: tcgpara);
  1303. begin
  1304. if not paramanager.ret_in_param(resdef,pd) then
  1305. begin
  1306. case resloc.location^.loc of
  1307. LOC_REGISTER,
  1308. LOC_FPUREGISTER,
  1309. LOC_MMREGISTER:
  1310. begin
  1311. if not llvmaggregatetype(resdef) then
  1312. list.concat(taillvm.op_reg_size_undef(la_bitcast,resloc.location^.register,llvmgetcgparadef(resloc,true,calleeside)))
  1313. else
  1314. { bitcast doesn't work for aggregates -> just load from the
  1315. (uninitialised) function result memory location }
  1316. gen_load_loc_function_result(list,resdef,tabstractnormalvarsym(pd.funcretsym).localloc)
  1317. end;
  1318. { for empty record returns }
  1319. LOC_VOID:
  1320. ;
  1321. else
  1322. internalerror(2015042301);
  1323. end;
  1324. end;
  1325. end;
  1326. procedure thlcgllvm.g_overflowcheck(list: TAsmList; const Loc: tlocation; def: tdef);
  1327. begin
  1328. { not possible, need ovloc }
  1329. internalerror(2012111107);
  1330. end;
  1331. procedure thlcgllvm.g_overflowCheck_loc(List: TAsmList; const Loc: TLocation; def: TDef; var ovloc: tlocation);
  1332. var
  1333. hl: tasmlabel;
  1334. begin
  1335. if not(cs_check_overflow in current_settings.localswitches) then
  1336. exit;
  1337. if ovloc.size<>OS_8 then
  1338. internalerror(2015122504);
  1339. current_asmdata.getjumplabel(hl);
  1340. a_cmp_const_loc_label(list,llvmbool1type,OC_EQ,0,ovloc,hl);
  1341. g_call_system_proc(list,'fpc_overflow',[],nil).resetiftemp;
  1342. a_label(list,hl);
  1343. end;
  1344. procedure thlcgllvm.g_ptrtypecast_reg(list: TAsmList; fromdef, todef: tdef; var reg: tregister);
  1345. var
  1346. hreg: tregister;
  1347. begin
  1348. { will insert a bitcast if necessary }
  1349. if fromdef<>todef then
  1350. begin
  1351. hreg:=getregisterfordef(list,todef);
  1352. a_load_reg_reg(list,fromdef,todef,reg,hreg);
  1353. reg:=hreg;
  1354. end;
  1355. end;
  1356. procedure thlcgllvm.g_ptrtypecast_ref(list: TAsmList; fromdef, todef: tdef; var ref: treference);
  1357. var
  1358. hreg: tregister;
  1359. begin
  1360. hreg:=getaddressregister(list,todef);
  1361. a_loadaddr_ref_reg_intern(list,fromdef,todef,ref,hreg,false);
  1362. reference_reset_base(ref,todef,hreg,0,ref.temppos,ref.alignment,ref.volatility);
  1363. end;
  1364. procedure thlcgllvm.g_set_addr_nonbitpacked_field_ref(list: TAsmList; recdef: tabstractrecorddef; field: tfieldvarsym; var recref: treference);
  1365. var
  1366. parentdef,
  1367. subscriptdef,
  1368. currentstructdef,
  1369. llvmfielddef: tdef;
  1370. llvmfield: tllvmshadowsymtableentry;
  1371. newbase: tregister;
  1372. implicitpointer: boolean;
  1373. begin
  1374. implicitpointer:=is_implicit_pointer_object_type(recdef);
  1375. currentstructdef:=recdef;
  1376. { in case the field is part of a parent of the current object,
  1377. index into the parents until we're at the parent containing the
  1378. field; if it's an implicit pointer type, these embedded parents
  1379. will be of the structure type of the class rather than of the
  1380. class time itself -> one indirection fewer }
  1381. while field.owner<>tabstractrecorddef(currentstructdef).symtable do
  1382. begin
  1383. { only objectdefs have parents and hence the owner of the
  1384. fieldvarsym can be different from the current def's owner }
  1385. parentdef:=tobjectdef(currentstructdef).childof;
  1386. if implicitpointer then
  1387. newbase:=getaddressregister(list,parentdef)
  1388. else
  1389. newbase:=getaddressregister(list,cpointerdef.getreusable(parentdef));
  1390. recref:=make_simple_ref(list,recref,recdef);
  1391. if implicitpointer then
  1392. subscriptdef:=currentstructdef
  1393. else
  1394. subscriptdef:=cpointerdef.getreusable(currentstructdef);
  1395. { recurse into the first field }
  1396. list.concat(taillvm.getelementptr_reg_size_ref_size_const(newbase,subscriptdef,recref,s32inttype,0,true));
  1397. reference_reset_base(recref,subscriptdef,newbase,field.offsetfromllvmfield,recref.temppos,newalignment(recref.alignment,field.fieldoffset),recref.volatility);
  1398. { go to the parent }
  1399. currentstructdef:=parentdef;
  1400. end;
  1401. { get the corresponding field in the llvm shadow symtable }
  1402. llvmfield:=tabstractrecordsymtable(tabstractrecorddef(currentstructdef).symtable).llvmst[field];
  1403. if implicitpointer then
  1404. subscriptdef:=currentstructdef
  1405. else
  1406. subscriptdef:=cpointerdef.getreusable(currentstructdef);
  1407. { load the address of that shadow field }
  1408. newbase:=getaddressregister(list,cpointerdef.getreusable(llvmfield.def));
  1409. recref:=make_simple_ref(list,recref,recdef);
  1410. list.concat(taillvm.getelementptr_reg_size_ref_size_const(newbase,subscriptdef,recref,s32inttype,field.llvmfieldnr,true));
  1411. reference_reset_base(recref,subscriptdef,newbase,field.offsetfromllvmfield,recref.temppos,newalignment(recref.alignment,llvmfield.fieldoffset+field.offsetfromllvmfield),recref.volatility);
  1412. { in case of an 80 bits extended type, typecast from an array of 10
  1413. bytes (used because otherwise llvm will allocate the ABI-defined
  1414. size for extended, which is usually larger) into an extended }
  1415. if (llvmfield.def.typ=floatdef) and
  1416. (tfloatdef(llvmfield.def).floattype=s80real) then
  1417. g_ptrtypecast_ref(list,cpointerdef.getreusable(carraydef.getreusable(u8inttype,10)),cpointerdef.getreusable(s80floattype),recref);
  1418. { if it doesn't match the requested field exactly (variant record),
  1419. adjust the type of the pointer }
  1420. if (field.offsetfromllvmfield<>0) or
  1421. (llvmfield.def<>field.vardef) then
  1422. g_ptrtypecast_ref(list,cpointerdef.getreusable(llvmfield.def),cpointerdef.getreusable(field.vardef),recref);
  1423. end;
  1424. procedure thlcgllvm.a_loadmm_ref_reg(list: TAsmList; fromsize, tosize: tdef; const ref: treference; reg: tregister; shuffle: pmmshuffle);
  1425. var
  1426. href: treference;
  1427. begin
  1428. if shuffle=mms_movescalar then
  1429. a_loadfpu_ref_reg(list,fromsize,tosize,ref,reg)
  1430. else
  1431. begin
  1432. href:=make_simple_ref(list,ref,fromsize);
  1433. if ref.refaddr=addr_full then
  1434. gen_load_refaddrfull_anyreg(list,fromsize,tosize,href,reg,shuffle)
  1435. else
  1436. begin
  1437. { handle aggregate loads (happens if a struct needs to be passed
  1438. in an mmregister) }
  1439. if (fromsize.typ in [arraydef,recorddef]) or
  1440. (tosize.typ in [arraydef,recorddef]) then
  1441. begin
  1442. if handle_agg_load_ref_anyreg(list,fromsize,tosize,href,reg,mms_movescalar) then
  1443. exit;
  1444. end;
  1445. if fromsize<>tosize then
  1446. g_ptrtypecast_ref(list,cpointerdef.getreusable(fromsize),cpointerdef.getreusable(tosize),href);
  1447. { %reg = load size* %ref }
  1448. list.concat(taillvm.op_reg_size_ref(la_load,reg,cpointerdef.getreusable(tosize),href));
  1449. end;
  1450. end;
  1451. end;
  1452. procedure thlcgllvm.a_loadmm_reg_ref(list: TAsmList; fromsize, tosize: tdef; reg: tregister; const ref: treference; shuffle: pmmshuffle);
  1453. var
  1454. href: treference;
  1455. begin
  1456. if shuffle=mms_movescalar then
  1457. a_loadfpu_reg_ref(list,fromsize,tosize,reg,ref)
  1458. else
  1459. begin
  1460. { todo }
  1461. if fromsize<>tosize then
  1462. internalerror(2013060220);
  1463. href:=make_simple_ref(list,ref,tosize);
  1464. { store tosize reg, tosize* href }
  1465. list.concat(taillvm.op_size_reg_size_ref(la_store,tosize,reg,cpointerdef.getreusable(tosize),href))
  1466. end;
  1467. end;
  1468. procedure thlcgllvm.a_loadmm_reg_reg(list: TAsmList; fromsize, tosize: tdef; reg1, reg2: tregister; shuffle: pmmshuffle);
  1469. begin
  1470. if shuffle=mms_movescalar then
  1471. a_loadfpu_reg_reg(list,fromsize,tosize,reg1,reg2)
  1472. else
  1473. { reg2 = bitcast fromllsize reg1 to tollsize }
  1474. list.concat(taillvm.op_reg_size_reg_size(la_bitcast,reg2,fromsize,reg1,tosize));
  1475. end;
  1476. procedure thlcgllvm.a_opmm_reg_reg(list: TAsmList; Op: TOpCG; size: tdef; src, dst: tregister; shuffle: pmmshuffle);
  1477. begin
  1478. if (op=OP_XOR) and
  1479. (src=dst) then
  1480. a_load_const_reg(list,size,0,dst)
  1481. else
  1482. { todo }
  1483. internalerror(2013060221);
  1484. end;
  1485. procedure thlcgllvm.a_loadmm_intreg_reg(list: TAsmList; fromsize, tosize: tdef; intreg, mmreg: tregister; shuffle: pmmshuffle);
  1486. begin
  1487. internalerror(2013060222);
  1488. end;
  1489. procedure thlcgllvm.a_loadmm_reg_intreg(list: TAsmList; fromsize, tosize: tdef; mmreg, intreg: tregister; shuffle: pmmshuffle);
  1490. begin
  1491. internalerror(2013060223);
  1492. end;
  1493. function thlcgllvm.get_call_result_cgpara(pd: tabstractprocdef; forceresdef: tdef): tcgpara;
  1494. var
  1495. paraloc: pcgparalocation;
  1496. begin
  1497. result:=inherited;
  1498. { we'll change the paraloc, make sure we don't modify the original one }
  1499. if not result.temporary then
  1500. begin
  1501. result:=result.getcopy;
  1502. result.temporary:=true;
  1503. end;
  1504. { get the LLVM representation of the function result (e.g. a
  1505. struct with two i64 fields for a record with 4 i32 fields) }
  1506. result.def:=llvmgetcgparadef(result,true,callerside);
  1507. if assigned(result.location^.next) then
  1508. begin
  1509. { unify the result into a sinlge location; unlike for parameters,
  1510. we are not responsible for splitting up results into multiple
  1511. locations }
  1512. { set the first location to the type of the function result }
  1513. result.location^.def:=result.def;
  1514. result.location^.size:=result.size;
  1515. { free all extra paralocs }
  1516. while assigned(result.location^.next) do
  1517. begin
  1518. paraloc:=result.location^.next^.next;
  1519. freemem(result.location^.next);
  1520. result.location^.next:=paraloc;
  1521. end;
  1522. end;
  1523. paraloc:=result.location;
  1524. paraloc^.def:=result.def;
  1525. case paraloc^.loc of
  1526. LOC_VOID:
  1527. ;
  1528. LOC_REGISTER,
  1529. LOC_FPUREGISTER,
  1530. LOC_MMREGISTER:
  1531. begin
  1532. paraloc^.llvmloc.loc:=paraloc^.loc;
  1533. paraloc^.llvmloc.reg:=paraloc^.register;
  1534. paraloc^.llvmvalueloc:=true;
  1535. end;
  1536. LOC_REFERENCE:
  1537. if not paramanager.ret_in_param(pd.returndef,pd) then
  1538. { TODO, if this can happen at all }
  1539. internalerror(2014011901);
  1540. else
  1541. internalerror(2014011902);
  1542. end;
  1543. end;
  1544. procedure thlcgllvm.gen_load_loc_function_result(list: TAsmList; vardef: tdef; const l: tlocation);
  1545. var
  1546. retlocpara: tcgpara;
  1547. begin
  1548. retlocpara:=get_call_result_cgpara(current_procinfo.procdef,nil);
  1549. gen_load_loc_cgpara(list,vardef,l,retlocpara);
  1550. retlocpara.resetiftemp;
  1551. end;
  1552. procedure thlcgllvm.gen_load_loc_cgpara(list: TAsmList; vardef: tdef; const l: tlocation; const cgpara: tcgpara);
  1553. var
  1554. memloc: tlocation;
  1555. begin
  1556. if not(cgpara.location^.llvmvalueloc) then
  1557. begin
  1558. memloc:=l;
  1559. location_force_mem(list,memloc,vardef);
  1560. a_loadaddr_ref_cgpara(list,vardef,memloc.reference,cgpara);
  1561. end
  1562. else
  1563. inherited;
  1564. end;
  1565. procedure thlcgllvm.gen_load_cgpara_loc(list: TAsmList; vardef: tdef; const para: TCGPara; var destloc: tlocation; reusepara: boolean);
  1566. var
  1567. ploc : pcgparalocation;
  1568. hloc : tlocation;
  1569. href, href2 : treference;
  1570. hreg : tregister;
  1571. fielddef,
  1572. llvmparadef : tdef;
  1573. index : longint;
  1574. offset : pint;
  1575. userecord : boolean;
  1576. begin
  1577. { ignore e.g. empty records }
  1578. if (para.location^.loc=LOC_VOID) then
  1579. exit;
  1580. { If the parameter location is reused we don't need to copy
  1581. anything }
  1582. if (destloc.loc=LOC_REFERENCE) and
  1583. reusepara then
  1584. exit;
  1585. { get the equivalent llvm def used to pass the parameter (e.g. a record
  1586. with two int64 fields for passing a record consisiting of 8 bytes on
  1587. x86-64) }
  1588. llvmparadef:=llvmgetcgparadef(para,true,calleeside);
  1589. userecord:=
  1590. (llvmparadef<>para.def) and
  1591. assigned(para.location^.next);
  1592. if userecord then
  1593. begin
  1594. { llvmparadef is a record in this case, with every field corresponding
  1595. to a single paraloc }
  1596. if destloc.loc<>LOC_REFERENCE then
  1597. tg.gethltemp(list,llvmparadef,llvmparadef.size,tt_normal,href)
  1598. else
  1599. begin
  1600. hreg:=getaddressregister(list,cpointerdef.getreusable(llvmparadef));
  1601. a_loadaddr_ref_reg(list,vardef,cpointerdef.getreusable(llvmparadef),destloc.reference,hreg);
  1602. reference_reset_base(href,cpointerdef.getreusable(llvmparadef),hreg,0,destloc.reference.temppos,destloc.reference.alignment,destloc.reference.volatility);
  1603. end;
  1604. index:=0;
  1605. ploc:=para.location;
  1606. repeat
  1607. paraloctoloc(ploc,hloc);
  1608. g_setup_load_field_by_name(list,trecorddef(llvmparadef),'F'+tostr(index),href,href2,fielddef);
  1609. a_load_loc_ref(list,ploc^.def,fielddef,hloc,href2);
  1610. inc(index);
  1611. ploc:=ploc^.next;
  1612. until not assigned(ploc);
  1613. if destloc.loc<>LOC_REFERENCE then
  1614. tg.ungettemp(list,href);
  1615. end
  1616. else
  1617. begin
  1618. para.check_simple_location;
  1619. paraloctoloc(para.location,hloc);
  1620. case destloc.loc of
  1621. LOC_REFERENCE :
  1622. begin
  1623. case def2regtyp(llvmparadef) of
  1624. R_INTREGISTER,
  1625. R_ADDRESSREGISTER:
  1626. a_load_loc_ref(list,llvmparadef,vardef,hloc,destloc.reference);
  1627. R_FPUREGISTER:
  1628. a_loadfpu_loc_ref(list,llvmparadef,vardef,hloc,destloc.reference);
  1629. R_MMREGISTER:
  1630. a_loadmm_loc_ref(list,llvmparadef,vardef,hloc,destloc.reference,nil);
  1631. else
  1632. internalerror(2014080801);
  1633. end;
  1634. end;
  1635. LOC_REGISTER:
  1636. begin
  1637. a_load_loc_reg(list,llvmparadef,vardef,hloc,destloc.register);
  1638. end;
  1639. LOC_FPUREGISTER:
  1640. begin
  1641. a_loadfpu_loc_reg(list,llvmparadef,vardef,hloc,destloc.register);
  1642. end;
  1643. LOC_MMREGISTER:
  1644. begin
  1645. a_loadmm_loc_reg(list,llvmparadef,vardef,hloc,destloc.register,nil);
  1646. end;
  1647. { TODO other possible locations }
  1648. else
  1649. internalerror(2013102304);
  1650. end;
  1651. end;
  1652. end;
  1653. procedure thlcgllvm.a_jmp_flags(list: TAsmList; const f: TResFlags; l: tasmlabel);
  1654. begin
  1655. internalerror(2013060224);
  1656. end;
  1657. procedure thlcgllvm.g_flags2reg(list: TAsmList; size: tdef; const f: tresflags; reg: TRegister);
  1658. begin
  1659. internalerror(2013060225);
  1660. end;
  1661. procedure thlcgllvm.g_flags2ref(list: TAsmList; size: tdef; const f: tresflags; const ref: TReference);
  1662. begin
  1663. internalerror(2013060226);
  1664. end;
  1665. procedure thlcgllvm.a_bit_scan_reg_reg(list: TAsmList; reverse: boolean; srcsize, dstsize: tdef; src, dst: tregister);
  1666. begin
  1667. internalerror(2012090201);
  1668. end;
  1669. procedure thlcgllvm.g_stackpointer_alloc(list: TAsmList; size: longint);
  1670. begin
  1671. internalerror(2012090203);
  1672. end;
  1673. procedure thlcgllvm.g_intf_wrapper(list: TAsmList; procdef: tprocdef; const labelname: string; ioffset: longint);
  1674. begin
  1675. internalerror(2012090204);
  1676. end;
  1677. procedure thlcgllvm.g_adjust_self_value(list: TAsmList; procdef: tprocdef; ioffset: aint);
  1678. begin
  1679. internalerror(2012090205);
  1680. end;
  1681. procedure thlcgllvm.g_local_unwind(list: TAsmList; l: TAsmLabel);
  1682. begin
  1683. internalerror(2012090206);
  1684. end;
  1685. procedure thlcgllvm.gen_stack_check_size_para(list: TAsmList);
  1686. begin
  1687. { this is implemented in a very hackish way, whereby first the call
  1688. to fpc_stackcheck() is emitted, then the prolog is generated and
  1689. registers are allocated, and finally the code to load the parameter
  1690. is inserted before the call to fpc_stackcheck(). Since parameters are
  1691. explicitly passed to call instructions for llvm, that does not work
  1692. here. It could be solved by patching the call instruction later, but
  1693. that's a lot of engineering for functionality that's only marginally
  1694. useful at best. }
  1695. end;
  1696. procedure thlcgllvm.gen_stack_check_call(list: TAsmList);
  1697. begin
  1698. { see explanation in thlcgllvm.gen_stack_check_size_para() }
  1699. end;
  1700. function thlcgllvm.make_simple_ref(list: TAsmList; const ref: treference; def: tdef): treference;
  1701. begin
  1702. result:=make_simple_ref_ptr(list,ref,cpointerdef.getreusable(def));
  1703. end;
  1704. function thlcgllvm.make_simple_ref_ptr(list: TAsmList; const ref: treference; ptrdef: tdef): treference;
  1705. var
  1706. ptrindex: tcgint;
  1707. hreg1,
  1708. hreg2: tregister;
  1709. tmpref: treference;
  1710. pointedsize: asizeint;
  1711. begin
  1712. if ref.alignment=0 then
  1713. internalerror(2016072203);
  1714. { already simple? }
  1715. if (not assigned(ref.symbol) or
  1716. (ref.base=NR_NO)) and
  1717. (ref.index=NR_NO) and
  1718. (ref.offset=0) then
  1719. begin
  1720. result:=ref;
  1721. exit;
  1722. end;
  1723. case ptrdef.typ of
  1724. pointerdef:
  1725. begin
  1726. pointedsize:=tpointerdef(ptrdef).pointeddef.size;
  1727. { void, formaldef }
  1728. if pointedsize=0 then
  1729. pointedsize:=1;
  1730. end;
  1731. else
  1732. begin
  1733. { pointedsize is only used if the offset <> 0, to see whether we
  1734. can use getelementptr if it's an exact multiple -> set pointedsize
  1735. to a value that will never be a multiple as we can't "index" other
  1736. types }
  1737. pointedsize:=ref.offset+1;
  1738. end;
  1739. end;
  1740. hreg2:=getaddressregister(list,ptrdef);
  1741. { symbol+offset or base+offset with offset a multiple of the size ->
  1742. use getelementptr }
  1743. if (ref.index=NR_NO) and
  1744. (ref.offset mod pointedsize=0) then
  1745. begin
  1746. ptrindex:=ref.offset div pointedsize;
  1747. if assigned(ref.symbol) then
  1748. reference_reset_symbol(tmpref,ref.symbol,0,ref.alignment,ref.volatility)
  1749. else
  1750. reference_reset_base(tmpref,ptrdef,ref.base,0,ref.temppos,ref.alignment,ref.volatility);
  1751. list.concat(taillvm.getelementptr_reg_size_ref_size_const(hreg2,ptrdef,tmpref,ptruinttype,ptrindex,assigned(ref.symbol)));
  1752. reference_reset_base(result,ptrdef,hreg2,0,ref.temppos,ref.alignment,ref.volatility);
  1753. exit;
  1754. end;
  1755. { for now, perform all calculations using plain pointer arithmetic. Later
  1756. we can look into optimizations based on getelementptr for structured
  1757. accesses (if only to prevent running out of virtual registers).
  1758. Assumptions:
  1759. * symbol/base register: always type "ptrdef"
  1760. * index/offset: always type "ptruinttype" (llvm bitcode has no sign information, so sign doesn't matter) }
  1761. hreg1:=getintregister(list,ptruinttype);
  1762. if assigned(ref.symbol) then
  1763. begin
  1764. if ref.base<>NR_NO then
  1765. internalerror(2012111301);
  1766. reference_reset_symbol(tmpref,ref.symbol,0,ref.alignment,ref.volatility);
  1767. list.concat(taillvm.getelementptr_reg_size_ref_size_const(hreg1,ptrdef,tmpref,ptruinttype,0,true));
  1768. end
  1769. else if ref.base<>NR_NO then
  1770. begin
  1771. a_load_reg_reg(list,ptrdef,ptruinttype,ref.base,hreg1);
  1772. end
  1773. else
  1774. { for absolute addresses }
  1775. a_load_const_reg(list,ptruinttype,0,hreg1);
  1776. if ref.index<>NR_NO then
  1777. begin
  1778. { SSA... }
  1779. hreg2:=getintregister(list,ptruinttype);
  1780. a_op_reg_reg_reg(list,OP_ADD,ptruinttype,ref.index,hreg1,hreg2);
  1781. hreg1:=hreg2;
  1782. end;
  1783. if ref.offset<>0 then
  1784. begin
  1785. hreg2:=getintregister(list,ptruinttype);
  1786. a_op_const_reg_reg(list,OP_ADD,ptruinttype,ref.offset,hreg1,hreg2);
  1787. hreg1:=hreg2;
  1788. end;
  1789. hreg2:=getaddressregister(list,ptrdef);
  1790. a_load_reg_reg(list,ptruinttype,ptrdef,hreg1,hreg2);
  1791. reference_reset_base(result,ptrdef,hreg2,0,ref.temppos,ref.alignment,ref.volatility);
  1792. end;
  1793. procedure thlcgllvm.set_call_function_result(const list: TAsmList; const pd: tabstractprocdef; const llvmretdef, hlretdef: tdef; const resval: tregister; var retpara: tcgpara);
  1794. var
  1795. hreg: tregister;
  1796. rettemp: treference;
  1797. begin
  1798. if (not is_void(hlretdef) and
  1799. not paramanager.ret_in_param(hlretdef, pd)) or
  1800. pd.generate_safecall_wrapper then
  1801. begin
  1802. { should already be a copy, because it currently describes the llvm
  1803. return location }
  1804. if not retpara.temporary then
  1805. internalerror(2014020101);
  1806. if llvmaggregatetype(hlretdef) then
  1807. begin
  1808. { to ease the handling of aggregate types here, we just store
  1809. everything to memory rather than potentially dealing with aggregates
  1810. in "registers" }
  1811. tg.gethltemp(list, llvmretdef, llvmretdef.size, tt_normal, rettemp);
  1812. case def2regtyp(llvmretdef) of
  1813. R_INTREGISTER,
  1814. R_ADDRESSREGISTER:
  1815. a_load_reg_ref(list,llvmretdef,llvmretdef,resval,rettemp);
  1816. R_FPUREGISTER:
  1817. a_loadfpu_reg_ref(list,llvmretdef,llvmretdef,resval,rettemp);
  1818. R_MMREGISTER:
  1819. a_loadmm_reg_ref(list,llvmretdef,llvmretdef,resval,rettemp,mms_movescalar);
  1820. else
  1821. ;
  1822. end;
  1823. { the return parameter now contains a value whose type matches the one
  1824. that the high level code generator expects instead of the llvm shim
  1825. }
  1826. retpara.def:=llvmretdef;
  1827. retpara.location^.def:=llvmretdef;
  1828. { for llvm-specific code: }
  1829. retpara.location^.llvmvalueloc:=false;
  1830. retpara.location^.llvmloc.loc:=LOC_REGISTER;
  1831. retpara.location^.llvmloc.reg:=rettemp.base;
  1832. { for the rest (normally not used, but cleaner to set it correclty) }
  1833. retpara.location^.loc:=LOC_REFERENCE;
  1834. retpara.location^.reference.index:=rettemp.base;
  1835. retpara.location^.reference.offset:=0;
  1836. end
  1837. else
  1838. begin
  1839. retpara.def:=llvmretdef;
  1840. retpara.Location^.def:=llvmretdef;
  1841. retpara.location^.llvmloc.reg:=resval;
  1842. retpara.Location^.llvmloc.loc:=retpara.location^.loc;
  1843. retpara.Location^.llvmvalueloc:=true;
  1844. end;
  1845. end
  1846. else
  1847. retpara.location^.llvmloc.loc:=LOC_VOID;
  1848. end;
  1849. procedure thlcgllvm.paraloctoloc(const paraloc: pcgparalocation; out hloc: tlocation);
  1850. begin
  1851. case paraloc^.llvmloc.loc of
  1852. LOC_REFERENCE:
  1853. begin
  1854. location_reset_ref(hloc,LOC_REFERENCE,def_cgsize(paraloc^.def),paraloc^.def.alignment,[]);
  1855. hloc.reference.symbol:=paraloc^.llvmloc.sym;
  1856. if paraloc^.llvmvalueloc then
  1857. hloc.reference.refaddr:=addr_full;
  1858. end;
  1859. LOC_REGISTER:
  1860. begin
  1861. if paraloc^.llvmvalueloc then
  1862. begin
  1863. location_reset(hloc,LOC_REGISTER,def_cgsize(paraloc^.def));
  1864. hloc.register:=paraloc^.llvmloc.reg;
  1865. end
  1866. else
  1867. begin
  1868. if getregtype(paraloc^.llvmloc.reg)<>R_TEMPREGISTER then
  1869. internalerror(2014011903);
  1870. location_reset_ref(hloc,LOC_REFERENCE,def_cgsize(paraloc^.def),paraloc^.def.alignment,[]);
  1871. hloc.reference.base:=paraloc^.llvmloc.reg;
  1872. end;
  1873. end;
  1874. LOC_FPUREGISTER,
  1875. LOC_MMREGISTER:
  1876. begin
  1877. if paraloc^.llvmvalueloc then
  1878. begin
  1879. location_reset(hloc,paraloc^.llvmloc.loc,def_cgsize(paraloc^.def));
  1880. hloc.register:=paraloc^.llvmloc.reg;
  1881. end
  1882. else
  1883. internalerror(2014012401);
  1884. end
  1885. else
  1886. internalerror(2014010706);
  1887. end;
  1888. end;
  1889. procedure thlcgllvm.varsym_set_localloc(list: TAsmList; vs: tabstractnormalvarsym);
  1890. begin
  1891. if cs_asm_source in current_settings.globalswitches then
  1892. begin
  1893. case vs.initialloc.loc of
  1894. LOC_REFERENCE :
  1895. begin
  1896. if assigned(vs.initialloc.reference.symbol) then
  1897. list.concat(Tai_comment.Create(strpnew('Var '+vs.realname+' located at '+
  1898. vs.initialloc.reference.symbol.name)))
  1899. else
  1900. list.concat(Tai_comment.Create(strpnew('Var '+vs.realname+' located at %tmp.'+
  1901. tostr(getsupreg(vs.initialloc.reference.base)))));
  1902. end;
  1903. else
  1904. ;
  1905. end;
  1906. end;
  1907. vs.localloc:=vs.initialloc;
  1908. end;
  1909. procedure thlcgllvm.paravarsym_set_initialloc_to_paraloc(vs: tparavarsym);
  1910. var
  1911. parasym : tasmsymbol;
  1912. begin
  1913. if vs.paraloc[calleeside].location^.llvmloc.loc<>LOC_REFERENCE then
  1914. internalerror(2014010708);
  1915. parasym:=vs.paraloc[calleeside].location^.llvmloc.sym;
  1916. reference_reset_symbol(vs.initialloc.reference,parasym,0,vs.paraloc[calleeside].alignment,[]);
  1917. if vs.paraloc[calleeside].location^.llvmvalueloc then
  1918. vs.initialloc.reference.refaddr:=addr_full;
  1919. end;
  1920. procedure thlcgllvm.g_external_wrapper(list: TAsmList; procdef: tprocdef; const wrappername, externalname: string; global: boolean);
  1921. var
  1922. asmsym: TAsmSymbol;
  1923. begin
  1924. if po_external in procdef.procoptions then
  1925. exit;
  1926. asmsym:=current_asmdata.RefAsmSymbol(externalname,AT_FUNCTION);
  1927. list.concat(taillvmalias.create(asmsym,wrappername,procdef,asmsym.bind));
  1928. end;
  1929. procedure create_hlcodegen_llvm;
  1930. begin
  1931. if not assigned(current_procinfo) or
  1932. not(po_assembler in current_procinfo.procdef.procoptions) then
  1933. begin
  1934. tgobjclass:=ttgllvm;
  1935. hlcg:=thlcgllvm.create;
  1936. cgllvm.create_codegen
  1937. end
  1938. else
  1939. begin
  1940. tgobjclass:=orgtgclass;
  1941. create_hlcodegen_cpu;
  1942. { todo: handle/remove chlcgobj }
  1943. end;
  1944. end;
  1945. begin
  1946. chlcgobj:=thlcgllvm;
  1947. { this unit must initialise after hlcgobj;
  1948. message system has not been initialised yet here }
  1949. if not assigned(create_hlcodegen) then
  1950. begin
  1951. writeln('Internalerror 2018052003');
  1952. halt(1);
  1953. end;
  1954. create_hlcodegen_cpu:=create_hlcodegen;
  1955. create_hlcodegen:=@create_hlcodegen_llvm;
  1956. end.