llvmdef.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. {
  2. Copyright (c) 2013 by Jonas Maebe
  3. This unit implements some LLVM type helper routines.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. {$i fpcdefs.inc}
  18. unit llvmdef;
  19. interface
  20. uses
  21. globtype,
  22. symbase,symtype,symdef;
  23. { Encode a type into the internal format used by LLVM. }
  24. function llvmencodetype(def: tdef): TSymStr;
  25. { incremental version of llvmencodetype(). "inaggregate" indicates whether
  26. this was a recursive call to get the type of an entity part of an
  27. aggregate type (array, record, ...) }
  28. procedure llvmaddencodedtype(def: tdef; inaggregate: boolean; var encodedstr: TSymStr);
  29. function llvmencodeproctype(def: tabstractprocdef; withprocname, withparanames: boolean): TSymStr;
  30. procedure llvmaddencodedproctype(def: tabstractprocdef; withprocname, withparanames: boolean; var encodedstr: TSymStr);
  31. { returns whether a def is representated by an aggregate type in llvm
  32. (struct, array) }
  33. function llvmaggregatetype(def: tdef): boolean;
  34. implementation
  35. uses
  36. cutils,cclasses,constexp,
  37. verbose,systems,
  38. fmodule,
  39. symtable,symconst,symsym,
  40. llvmsym,
  41. defutil,cgbase,parabase,paramgr;
  42. {******************************************************************
  43. Type encoding
  44. *******************************************************************}
  45. function llvmaggregatetype(def: tdef): boolean;
  46. begin
  47. result:=
  48. (def.typ in [recorddef,filedef,variantdef]) or
  49. ((def.typ=arraydef) and
  50. not is_dynamic_array(def)) or
  51. ((def.typ=setdef) and
  52. not is_smallset(def)) or
  53. is_shortstring(def) or
  54. is_object(def) or
  55. ((def.typ=procvardef) and
  56. not tprocvardef(def).is_addressonly)
  57. end;
  58. procedure llvmaddencodedabstractrecordtype(def: tabstractrecorddef; var encodedstr: TSymStr); forward;
  59. procedure llvmaddencodedtype_intern(def: tdef; inaggregate, noimplicitderef: boolean; var encodedstr: TSymStr);
  60. begin
  61. case def.typ of
  62. stringdef :
  63. begin
  64. case tstringdef(def).stringtype of
  65. st_widestring,
  66. st_unicodestring:
  67. { the variable does not point to the header, but to a
  68. null-terminated string/array with undefined bounds }
  69. encodedstr:=encodedstr+'[0 x i16]';
  70. st_ansistring:
  71. encodedstr:=encodedstr+'[0 x i8]';
  72. st_shortstring:
  73. { length byte followed by string bytes }
  74. if tstringdef(def).len>0 then
  75. encodedstr:=encodedstr+'{i8, ['+tostr(tstringdef(def).len)+' x i8]}'
  76. else
  77. encodedstr:=encodedstr+'{i8, [0 x i8]}';
  78. else
  79. internalerror(2013100201);
  80. end;
  81. end;
  82. enumdef:
  83. begin
  84. encodedstr:=encodedstr+'i'+tostr(def.size*8);
  85. end;
  86. orddef :
  87. begin
  88. if is_void(def) then
  89. encodedstr:=encodedstr+'void'
  90. { mainly required because comparison operations return i1, and
  91. otherwise we always have to immediatel extend them to i8 for
  92. no good reason; besides, Pascal booleans can only contain 0
  93. or 1 in valid code anyway (famous last words...) }
  94. else if torddef(def).ordtype=pasbool8 then
  95. encodedstr:=encodedstr+'i1'
  96. else
  97. encodedstr:=encodedstr+'i'+tostr(def.size*8);
  98. end;
  99. pointerdef :
  100. begin
  101. if is_voidpointer(def) then
  102. encodedstr:=encodedstr+'i8*'
  103. else
  104. begin
  105. llvmaddencodedtype_intern(tpointerdef(def).pointeddef,inaggregate,false,encodedstr);
  106. encodedstr:=encodedstr+'*';
  107. end;
  108. end;
  109. floatdef :
  110. begin
  111. case tfloatdef(def).floattype of
  112. s32real:
  113. encodedstr:=encodedstr+'float';
  114. s64real:
  115. encodedstr:=encodedstr+'double';
  116. { necessary to be able to force our own size/alignment }
  117. s80real:
  118. { prevent llvm from allocating the standard ABI size for
  119. extended }
  120. if inaggregate then
  121. encodedstr:=encodedstr+'[10 x i8]'
  122. else
  123. encodedstr:=encodedstr+'x86_fp80';
  124. sc80real:
  125. encodedstr:=encodedstr+'x86_fp80';
  126. s64comp,
  127. s64currency:
  128. encodedstr:=encodedstr+'i64';
  129. s128real:
  130. {$if defined(powerpc) or defined(powerpc128)}
  131. encodedstr:=encodedstr+'ppc_fp128';
  132. {$else}
  133. encodedstr:=encodedstr+'fp128';
  134. {$endif}
  135. else
  136. internalerror(2013100202);
  137. end;
  138. end;
  139. filedef :
  140. begin
  141. case tfiledef(def).filetyp of
  142. ft_text :
  143. llvmaddencodedtype_intern(search_system_type('TEXTREC').typedef,inaggregate,false,encodedstr);
  144. ft_typed,
  145. ft_untyped :
  146. llvmaddencodedtype_intern(search_system_type('FILEREC').typedef,inaggregate,false,encodedstr);
  147. else
  148. internalerror(2013100203);
  149. end;
  150. end;
  151. recorddef :
  152. begin
  153. llvmaddencodedabstractrecordtype(trecorddef(def),encodedstr);
  154. end;
  155. variantdef :
  156. begin
  157. llvmaddencodedtype_intern(search_system_type('TVARDATA').typedef,inaggregate,false,encodedstr);
  158. end;
  159. classrefdef :
  160. begin
  161. { todo: define proper type for VMT and use that }
  162. encodedstr:=encodedstr+'i8*';
  163. end;
  164. setdef :
  165. begin
  166. { just an array as far as llvm is concerned; don't use a "packed
  167. array of i1" or so, this requires special support in backends
  168. and guarantees nothing about the internal format }
  169. encodedstr:=encodedstr+'['+tostr(tsetdef(def).size)+' x i8]';
  170. end;
  171. formaldef :
  172. begin
  173. { var/const/out x }
  174. encodedstr:=encodedstr+'i8*';
  175. end;
  176. arraydef :
  177. begin
  178. if is_array_of_const(def) then
  179. begin
  180. encodedstr:=encodedstr+'[0 x ';
  181. llvmaddencodedtype_intern(search_system_type('TVARREC').typedef,true,false,encodedstr);
  182. encodedstr:=encodedstr+']';
  183. end
  184. else if is_open_array(def) then
  185. begin
  186. encodedstr:=encodedstr+'[0 x ';
  187. llvmaddencodedtype_intern(tarraydef(def).elementdef,true,false,encodedstr);
  188. encodedstr:=encodedstr+']';
  189. end
  190. else if is_dynamic_array(def) then
  191. begin
  192. llvmaddencodedtype_intern(tarraydef(def).elementdef,false,false,encodedstr);
  193. encodedstr:=encodedstr+'*';
  194. end
  195. else if is_packed_array(def) then
  196. begin
  197. encodedstr:=encodedstr+'['+tostr(tarraydef(def).size div tarraydef(def).elementdef.packedbitsize)+' x ';
  198. { encode as an array of integers with the size on which we
  199. perform the packedbits operations }
  200. llvmaddencodedtype_intern(cgsize_orddef(int_cgsize(packedbitsloadsize(tarraydef(def).elementdef.packedbitsize))),true,false,encodedstr);
  201. encodedstr:=encodedstr+']';
  202. end
  203. else
  204. begin
  205. encodedstr:=encodedstr+'['+tostr(tarraydef(def).elecount)+' x ';
  206. llvmaddencodedtype_intern(tarraydef(def).elementdef,true,false,encodedstr);
  207. encodedstr:=encodedstr+']';
  208. end;
  209. end;
  210. procvardef :
  211. begin
  212. if tprocvardef(def).is_addressonly then
  213. begin
  214. llvmaddencodedproctype(tprocdef(def),false,false,encodedstr);
  215. encodedstr:=encodedstr+'*';
  216. end
  217. else
  218. begin
  219. encodedstr:=encodedstr+'{';
  220. { code pointer }
  221. llvmaddencodedproctype(tprocvardef(def),false,false,encodedstr);
  222. { data pointer (maybe todo: generate actual layout if
  223. available) }
  224. encodedstr:=encodedstr+'*, i8*}';
  225. end;
  226. end;
  227. objectdef :
  228. case tobjectdef(def).objecttype of
  229. odt_class,
  230. odt_objcclass,
  231. odt_object,
  232. odt_cppclass:
  233. begin
  234. { for now don't handle fields yet }
  235. encodedstr:=encodedstr+'{[i8 x '+tostr(def.size)+']}';
  236. if not noimplicitderef and
  237. is_implicit_pointer_object_type(def) then
  238. encodedstr:=encodedstr+'*'
  239. end;
  240. odt_interfacecom,
  241. odt_interfacecom_function,
  242. odt_interfacecom_property,
  243. odt_interfacecorba,
  244. odt_dispinterface,
  245. odt_objcprotocol:
  246. begin
  247. { opaque for now }
  248. encodedstr:=encodedstr+'i8*'
  249. end;
  250. else
  251. internalerror(2013100601);
  252. end;
  253. undefineddef,
  254. errordef :
  255. internalerror(2013100604);
  256. procdef :
  257. begin
  258. llvmaddencodedproctype(tprocdef(def),true,false,encodedstr);
  259. end;
  260. else
  261. internalerror(2013100603);
  262. end;
  263. end;
  264. procedure llvmaddencodedtype(def: tdef; inaggregate: boolean; var encodedstr: TSymStr);
  265. begin
  266. llvmaddencodedtype_intern(def,inaggregate,false,encodedstr);
  267. end;
  268. procedure llvmaddencodedabstractrecordtype(def: tabstractrecorddef; var encodedstr: TSymStr);
  269. var
  270. st: tllvmshadowsymtable;
  271. symdeflist: tfpobjectlist;
  272. i: longint;
  273. begin
  274. st:=tabstractrecordsymtable(def.symtable).llvmst;
  275. symdeflist:=st.symdeflist;
  276. if tabstractrecordsymtable(def.symtable).usefieldalignment<>C_alignment then
  277. encodedstr:=encodedstr+'<';
  278. encodedstr:=encodedstr+'{ ';
  279. if symdeflist.count>0 then
  280. begin
  281. i:=0;
  282. if (def.typ=objectdef) and
  283. assigned(tobjectdef(def).childof) and
  284. is_class_or_interface_or_dispinterface(tllvmshadowsymtableentry(symdeflist[0]).def) then
  285. begin
  286. { insert the struct for the class rather than a pointer to the struct }
  287. if (tllvmshadowsymtableentry(symdeflist[0]).def.typ<>objectdef) then
  288. internalerror(2008070601);
  289. llvmaddencodedtype_intern(tllvmshadowsymtableentry(symdeflist[0]).def,true,true,encodedstr);
  290. inc(i);
  291. end;
  292. while i<symdeflist.count do
  293. begin
  294. if i<>0 then
  295. encodedstr:=encodedstr+', ';
  296. llvmaddencodedtype_intern(tllvmshadowsymtableentry(symdeflist[i]).def,true,false,encodedstr);
  297. inc(i);
  298. end;
  299. end;
  300. encodedstr:=encodedstr+' }';
  301. if tabstractrecordsymtable(def.symtable).usefieldalignment<>C_alignment then
  302. encodedstr:=encodedstr+'>';
  303. end;
  304. procedure llvmrefineordinaldef(paradef, paralocdef: tdef; out usedef: tdef; out signextstr: TSymStr);
  305. begin
  306. { implicit zero/sign extension for ABI compliance? (yes, if the size
  307. of a paraloc is larger than the size of the entire parameter) }
  308. if is_ordinal(paradef) and
  309. is_ordinal(paralocdef) and
  310. (paradef.size<paralocdef.size) then
  311. begin
  312. usedef:=paradef;
  313. if is_signed(paradef) then
  314. signextstr:='signext '
  315. else
  316. signextstr:='zeroext '
  317. end
  318. else
  319. begin
  320. usedef:=paralocdef;
  321. signextstr:='';
  322. end;
  323. end;
  324. procedure llvmaddencodedparaloctype(hp: tparavarsym; const para: tcgpara; proccalloption: tproccalloption; withparaname: boolean; var first: boolean; var encodedstr: TSymStr);
  325. { the default for llvm is to pass aggregates in integer registers or
  326. on the stack (as the ABI prescribes). Records that require special
  327. handling, e.g. (partly) passing in fpu registers, have to be handled
  328. explicitly. This function returns whether an aggregate is handled
  329. specially }
  330. function hasnondefaultparaloc: boolean;
  331. var
  332. loc: PCGParaLocation;
  333. begin
  334. loc:=para.Location;
  335. result:=true;
  336. while assigned(loc) do
  337. begin
  338. if not(loc^.loc in [LOC_REGISTER,LOC_REFERENCE]) then
  339. exit;
  340. end;
  341. result:=false;
  342. end;
  343. var
  344. paraloc: PCGParaLocation;
  345. signextstr: TSymStr;
  346. usedef: tdef;
  347. closestruct: boolean;
  348. begin
  349. { byval: a pointer to a type that should actually be passed by
  350. value (e.g. a record that should be passed on the stack) }
  351. if assigned(hp) and
  352. (hp.vardef.typ in [arraydef,recorddef,objectdef]) and
  353. not paramanager.push_addr_param(hp.varspez,hp.vardef,proccalloption) and
  354. not hasnondefaultparaloc then
  355. begin
  356. llvmaddencodedtype(hp.vardef,false,encodedstr);
  357. encodedstr:=encodedstr+'* byval';
  358. if withparaname then
  359. encodedstr:=encodedstr+' '+para.location^.llvmloc.name;
  360. exit;
  361. end;
  362. closestruct:=false;
  363. paraloc:=para.location;
  364. if not assigned(hp) then
  365. begin
  366. { if a function returns a composite value (e.g. 2 sse register),
  367. those are represented as a struct }
  368. if assigned(paraloc^.next) then
  369. begin
  370. encodedstr:=encodedstr+'{';
  371. closestruct:=true;
  372. end;
  373. end;
  374. repeat
  375. usedef:=paraloc^.def;
  376. llvmrefineordinaldef(para.def,paraloc^.def,usedef,signextstr);
  377. { implicit zero/sign extension for ABI compliance? }
  378. if not assigned(hp) then
  379. encodedstr:=encodedstr+signextstr;
  380. if not first then
  381. encodedstr:=encodedstr+', '
  382. else
  383. first:=false;
  384. llvmaddencodedtype(usedef,false,encodedstr);
  385. { in case signextstr<>'', there should be only one paraloc -> no need
  386. to clear (reason: it means that the paraloc is larger than the
  387. original parameter) }
  388. if assigned(hp) then
  389. encodedstr:=encodedstr+signextstr;
  390. if assigned(hp) then
  391. begin
  392. { sret: hidden pointer for structured function result }
  393. if vo_is_funcret in hp.varoptions then
  394. encodedstr:=encodedstr+' sret'
  395. end;
  396. if withparaname then
  397. encodedstr:=encodedstr+' '+paraloc^.llvmloc.name;
  398. paraloc:=paraloc^.next;
  399. until not assigned(paraloc);
  400. if closestruct then
  401. encodedstr:=encodedstr+'}'
  402. end;
  403. function llvmencodeproctype(def: tabstractprocdef; withprocname, withparanames: boolean): TSymStr;
  404. begin
  405. result:='';
  406. llvmaddencodedproctype(def,withprocname,withparanames,result);
  407. end;
  408. procedure llvmaddencodedproctype(def: tabstractprocdef; withprocname, withparanames: boolean; var encodedstr: TSymStr);
  409. var
  410. paranr: longint;
  411. para: tcgpara;
  412. hp: tparavarsym;
  413. first: boolean;
  414. begin
  415. def.init_paraloc_info(calleeside);
  416. first:=true;
  417. { function result (return-by-ref is handled explicitly) }
  418. if not paramanager.ret_in_param(def.returndef,def) then
  419. llvmaddencodedparaloctype(nil,def.funcretloc[calleeside],def.proccalloption,false,first,encodedstr)
  420. else
  421. llvmaddencodedtype(voidtype,false,encodedstr);
  422. encodedstr:=encodedstr+' ';
  423. if withprocname and
  424. (def.typ=procdef) then
  425. encodedstr:=encodedstr+tprocdef(def).mangledname;
  426. encodedstr:=encodedstr+'(';
  427. { parameters }
  428. first:=true;
  429. for paranr:=0 to def.paras.count-1 do
  430. begin
  431. hp:=tparavarsym(def.paras[paranr]);
  432. llvmaddencodedparaloctype(hp,hp.paraloc[calleeside],def.proccalloption,withparanames,first,encodedstr);
  433. end;
  434. encodedstr:=encodedstr+')'
  435. end;
  436. function llvmencodetype(def: tdef): TSymStr;
  437. begin
  438. result:='';
  439. llvmaddencodedtype(def,false,result);
  440. end;
  441. end.