llvmdef.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  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. implementation
  32. uses
  33. cutils,cclasses,constexp,
  34. verbose,systems,
  35. fmodule,
  36. symtable,symconst,symsym,
  37. llvmsym,
  38. defutil,cgbase,parabase,paramgr;
  39. {******************************************************************
  40. Type encoding
  41. *******************************************************************}
  42. procedure llvmaddencodedtype(def: tdef; inaggregate: boolean; var encodedstr: TSymStr);
  43. begin
  44. case def.typ of
  45. stringdef :
  46. begin
  47. case tstringdef(def).stringtype of
  48. st_widestring,
  49. st_unicodestring:
  50. { the variable does not point to the header, but to a
  51. null-terminated string/array with undefined bounds }
  52. encodedstr:=encodedstr+'[0 x i16]';
  53. st_ansistring:
  54. encodedstr:=encodedstr+'[0 x i8]';
  55. st_shortstring:
  56. { length byte followed by string bytes }
  57. if tstringdef(def).len>0 then
  58. encodedstr:=encodedstr+'{i8, ['+tostr(tstringdef(def).len)+' x i8]}'
  59. else
  60. encodedstr:=encodedstr+'{i8, [0 x i8]}';
  61. else
  62. internalerror(2013100201);
  63. end;
  64. end;
  65. enumdef:
  66. begin
  67. encodedstr:=encodedstr+'i'+tostr(def.size*8);
  68. end;
  69. orddef :
  70. begin
  71. if is_void(def) then
  72. encodedstr:=encodedstr+'void'
  73. { mainly required because comparison operations return i1, and
  74. otherwise we always have to immediatel extend them to i8 for
  75. no good reason; besides, Pascal booleans can only contain 0
  76. or 1 in valid code anyway (famous last words...) }
  77. else if torddef(def).ordtype=pasbool8 then
  78. encodedstr:=encodedstr+'i1'
  79. else
  80. encodedstr:=encodedstr+'i'+tostr(def.size*8);
  81. end;
  82. pointerdef :
  83. begin
  84. if is_voidpointer(def) then
  85. encodedstr:=encodedstr+'i8*'
  86. else
  87. begin
  88. llvmaddencodedtype(tpointerdef(def).pointeddef,false,encodedstr);
  89. encodedstr:=encodedstr+'*';
  90. end;
  91. end;
  92. floatdef :
  93. begin
  94. case tfloatdef(def).floattype of
  95. s32real:
  96. encodedstr:=encodedstr+'float';
  97. s64real:
  98. encodedstr:=encodedstr+'double';
  99. { necessary to be able to force our own size/alignment }
  100. s80real:
  101. { prevent llvm from allocating the standard ABI size for
  102. extended }
  103. if inaggregate then
  104. encodedstr:=encodedstr+'[10 x i8]'
  105. else
  106. encodedstr:=encodedstr+'x86_fp80';
  107. sc80real:
  108. encodedstr:=encodedstr+'x86_fp80';
  109. s64comp,
  110. s64currency:
  111. encodedstr:=encodedstr+'i64';
  112. s128real:
  113. {$if defined(powerpc) or defined(powerpc128)}
  114. encodedstr:=encodedstr+'ppc_fp128';
  115. {$else}
  116. encodedstr:=encodedstr+'fp128';
  117. {$endif}
  118. else
  119. internalerror(2013100202);
  120. end;
  121. end;
  122. filedef :
  123. begin
  124. case tfiledef(def).filetyp of
  125. ft_text :
  126. llvmaddencodedtype(search_system_type('TEXTREC').typedef,false,encodedstr);
  127. ft_typed,
  128. ft_untyped :
  129. llvmaddencodedtype(search_system_type('FILEREC').typedef,false,encodedstr);
  130. else
  131. internalerror(2013100203);
  132. end;
  133. end;
  134. recorddef :
  135. begin
  136. { for now don't encode the individual fields, because handling
  137. variant records is a pain. As far as correctness is concerned,
  138. the types of the fields only matter for the parameters and
  139. function result types, but for those we have to use what the
  140. parameter manager calculates anyway (because e.g. a record
  141. with two floats has to be passed in an SSE register on x86-64) }
  142. encodedstr:=encodedstr+'{[i8 x '+tostr(def.size)+']}'
  143. end;
  144. variantdef :
  145. begin
  146. llvmaddencodedtype(search_system_type('TVARDATA').typedef,false,encodedstr);
  147. end;
  148. classrefdef :
  149. begin
  150. { todo: define proper type for VMT and use that }
  151. encodedstr:=encodedstr+'i8*';
  152. end;
  153. setdef :
  154. begin
  155. { just an array as far as llvm is concerned; don't use a "packed
  156. array of i1" or so, this requires special support in backends
  157. and guarantees nothing about the internal format }
  158. encodedstr:=encodedstr+'['+tostr(tsetdef(def).size)+' x i8]';
  159. end;
  160. formaldef :
  161. begin
  162. { var/const/out x }
  163. encodedstr:=encodedstr+'i8*';
  164. end;
  165. arraydef :
  166. begin
  167. if is_array_of_const(def) then
  168. begin
  169. encodedstr:=encodedstr+'[0 x ';
  170. llvmaddencodedtype(search_system_type('TVARREC').typedef,true,encodedstr);
  171. encodedstr:=encodedstr+']';
  172. end
  173. else if is_open_array(def) then
  174. begin
  175. encodedstr:=encodedstr+'[0 x ';
  176. llvmaddencodedtype(tarraydef(def).elementdef,true,encodedstr);
  177. encodedstr:=encodedstr+']';
  178. end
  179. else if is_dynamic_array(def) then
  180. begin
  181. llvmaddencodedtype(tarraydef(def).elementdef,false,encodedstr);
  182. encodedstr:=encodedstr+'*';
  183. end
  184. else if is_packed_array(def) then
  185. begin
  186. encodedstr:=encodedstr+'['+tostr(tarraydef(def).size div tarraydef(def).elementdef.packedbitsize)+' x ';
  187. { encode as an array of integers with the size on which we
  188. perform the packedbits operations }
  189. llvmaddencodedtype(cgsize_orddef(int_cgsize(packedbitsloadsize(tarraydef(def).elementdef.packedbitsize))),true,encodedstr);
  190. encodedstr:=encodedstr+']';
  191. end
  192. else
  193. begin
  194. encodedstr:=encodedstr+'['+tostr(tarraydef(def).elecount)+' x ';
  195. llvmaddencodedtype(tarraydef(def).elementdef,true,encodedstr);
  196. encodedstr:=encodedstr+']';
  197. end;
  198. end;
  199. procvardef :
  200. begin
  201. if tprocvardef(def).is_addressonly then
  202. begin
  203. llvmaddencodedproctype(tprocdef(def),false,false,encodedstr);
  204. encodedstr:=encodedstr+'*';
  205. end
  206. else
  207. begin
  208. encodedstr:=encodedstr+'{';
  209. { code pointer }
  210. llvmaddencodedproctype(tprocvardef(def),false,false,encodedstr);
  211. { data pointer (maybe todo: generate actual layout if
  212. available) }
  213. encodedstr:=encodedstr+'*, i8*}';
  214. end;
  215. end;
  216. objectdef :
  217. case tobjectdef(def).objecttype of
  218. odt_class,
  219. odt_objcclass,
  220. odt_object,
  221. odt_cppclass:
  222. begin
  223. { for now don't handle fields yet }
  224. encodedstr:=encodedstr+'{[i8 x '+tostr(def.size)+']}';
  225. if is_implicit_pointer_object_type(def) then
  226. encodedstr:=encodedstr+'*'
  227. end;
  228. odt_interfacecom,
  229. odt_interfacecom_function,
  230. odt_interfacecom_property,
  231. odt_interfacecorba,
  232. odt_dispinterface,
  233. odt_objcprotocol:
  234. begin
  235. { opaque for now }
  236. encodedstr:=encodedstr+'i8*'
  237. end;
  238. else
  239. internalerror(2013100601);
  240. end;
  241. undefineddef,
  242. errordef :
  243. internalerror(2013100604);
  244. procdef :
  245. begin
  246. llvmaddencodedproctype(tprocdef(def),true,false,encodedstr);
  247. end;
  248. else
  249. internalerror(2013100603);
  250. end;
  251. end;
  252. procedure llvmrefineordinaldef(paradef, paralocdef: tdef; out usedef: tdef; out signextstr: TSymStr);
  253. begin
  254. { implicit zero/sign extension for ABI compliance? (yes, if the size
  255. of a paraloc is larger than the size of the entire parameter) }
  256. if is_ordinal(paradef) and
  257. is_ordinal(paralocdef) and
  258. (paradef.size<paralocdef.size) then
  259. begin
  260. usedef:=paradef;
  261. if is_signed(paradef) then
  262. signextstr:='signext '
  263. else
  264. signextstr:='zeroext '
  265. end
  266. else
  267. begin
  268. usedef:=paralocdef;
  269. signextstr:='';
  270. end;
  271. end;
  272. procedure llvmaddencodedparaloctype(hp: tparavarsym; const para: tcgpara; proccalloption: tproccalloption; withparaname: boolean; var first: boolean; var encodedstr: TSymStr);
  273. { the default for llvm is to pass aggregates in integer registers or
  274. on the stack (as the ABI prescribes). Records that require special
  275. handling, e.g. (partly) passing in fpu registers, have to be handled
  276. explicitly. This function returns whether an aggregate is handled
  277. specially }
  278. function hasnondefaultparaloc: boolean;
  279. var
  280. loc: PCGParaLocation;
  281. begin
  282. loc:=para.Location;
  283. result:=true;
  284. while assigned(loc) do
  285. begin
  286. if not(loc^.loc in [LOC_REGISTER,LOC_REFERENCE]) then
  287. exit;
  288. end;
  289. result:=false;
  290. end;
  291. var
  292. paraloc: PCGParaLocation;
  293. signextstr: TSymStr;
  294. usedef: tdef;
  295. closestruct: boolean;
  296. begin
  297. { byval: a pointer to a type that should actually be passed by
  298. value (e.g. a record that should be passed on the stack) }
  299. if assigned(hp) and
  300. (hp.vardef.typ in [arraydef,recorddef,objectdef]) and
  301. not paramanager.push_addr_param(hp.varspez,hp.vardef,proccalloption) and
  302. not hasnondefaultparaloc then
  303. begin
  304. llvmaddencodedtype(hp.vardef,false,encodedstr);
  305. encodedstr:=encodedstr+'* byval';
  306. if withparaname then
  307. encodedstr:=encodedstr+' '+para.location^.llvmloc.name;
  308. exit;
  309. end;
  310. closestruct:=false;
  311. paraloc:=para.location;
  312. if not assigned(hp) then
  313. begin
  314. { if a function returns a composite value (e.g. 2 sse register),
  315. those are represented as a struct }
  316. if assigned(paraloc^.next) then
  317. begin
  318. encodedstr:=encodedstr+'{';
  319. closestruct:=true;
  320. end;
  321. end;
  322. repeat
  323. usedef:=paraloc^.def;
  324. llvmrefineordinaldef(para.def,paraloc^.def,usedef,signextstr);
  325. { implicit zero/sign extension for ABI compliance? }
  326. if not assigned(hp) then
  327. encodedstr:=encodedstr+signextstr;
  328. if not first then
  329. encodedstr:=encodedstr+', '
  330. else
  331. first:=false;
  332. llvmaddencodedtype(usedef,false,encodedstr);
  333. { in case signextstr<>'', there should be only one paraloc -> no need
  334. to clear (reason: it means that the paraloc is larger than the
  335. original parameter) }
  336. if assigned(hp) then
  337. encodedstr:=encodedstr+signextstr;
  338. if assigned(hp) then
  339. begin
  340. { sret: hidden pointer for structured function result }
  341. if vo_is_funcret in hp.varoptions then
  342. encodedstr:=encodedstr+' sret'
  343. end;
  344. if withparaname then
  345. encodedstr:=encodedstr+' '+paraloc^.llvmloc.name;
  346. paraloc:=paraloc^.next;
  347. until not assigned(paraloc);
  348. if closestruct then
  349. encodedstr:=encodedstr+'}'
  350. end;
  351. function llvmencodeproctype(def: tabstractprocdef; withprocname, withparanames: boolean): TSymStr;
  352. begin
  353. result:='';
  354. llvmaddencodedproctype(def,withprocname,withparanames,result);
  355. end;
  356. procedure llvmaddencodedproctype(def: tabstractprocdef; withprocname, withparanames: boolean; var encodedstr: TSymStr);
  357. var
  358. paranr: longint;
  359. para: tcgpara;
  360. hp: tparavarsym;
  361. first: boolean;
  362. begin
  363. def.init_paraloc_info(calleeside);
  364. first:=true;
  365. { function result (return-by-ref is handled explicitly) }
  366. if not paramanager.ret_in_param(def.returndef,def) then
  367. llvmaddencodedparaloctype(nil,def.funcretloc[calleeside],def.proccalloption,false,first,encodedstr)
  368. else
  369. llvmaddencodedtype(voidtype,false,encodedstr);
  370. encodedstr:=encodedstr+' ';
  371. if withprocname and
  372. (def.typ=procdef) then
  373. encodedstr:=encodedstr+tprocdef(def).mangledname;
  374. encodedstr:=encodedstr+'(';
  375. { parameters }
  376. first:=true;
  377. for paranr:=0 to def.paras.count-1 do
  378. begin
  379. hp:=tparavarsym(def.paras[paranr]);
  380. llvmaddencodedparaloctype(hp,hp.paraloc[calleeside],def.proccalloption,withparanames,first,encodedstr);
  381. end;
  382. encodedstr:=encodedstr+')'
  383. end;
  384. function llvmencodetype(def: tdef): TSymStr;
  385. begin
  386. result:='';
  387. llvmaddencodedtype(def,false,result);
  388. end;
  389. end.