aasmllvmmetadata.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492
  1. {
  2. Copyright (c) 2019 by Jonas Maebe,
  3. member of the Free Pascal Compiler development team
  4. Support for LLVM metadata
  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 aasmllvmmetadata;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,cclasses,
  23. cgbase,
  24. aasmtai,aasmcnst,
  25. symtype;
  26. {$push}{$ScopedEnums on}
  27. type
  28. tspecialisedmetadatanodekind = (
  29. DICompileUnit,
  30. DIFile,
  31. DIBasicType,
  32. DISubroutineType,
  33. DIDerivedType,
  34. DICompositeType,
  35. DISubrange,
  36. DIEnumerator,
  37. DITemplateTypeParameter,
  38. DITemplateValueParameter,
  39. DINamespace,
  40. DIGlobalVariable,
  41. DISubprogram,
  42. DILexicalBlock,
  43. DILexicalBlockFile,
  44. DILocation,
  45. DILocalVariable,
  46. DIExpression,
  47. DIObjCProperty,
  48. DIImportedEntity,
  49. DIMacro,
  50. DIMacroFile
  51. );
  52. {$pop}
  53. // represented by a tai_simpletypedconst() with inside a metadata struct,
  54. // or as a metadata register (for parameters)
  55. // tai_llvmmetadatastring = class
  56. tai_llvmbasemetadatanode = class abstract(tai_aggregatetypedconst)
  57. strict protected
  58. function getname: ansistring; virtual; abstract;
  59. public
  60. procedure addvalue(val: tai_abstracttypedconst); override;
  61. property name: ansistring read getname;
  62. constructor create; reintroduce;
  63. class function isspecialised: boolean; virtual;
  64. end;
  65. (* !0 = !{ type1 value1, ... } *)
  66. tai_llvmunnamedmetadatanode = class(tai_llvmbasemetadatanode)
  67. strict private
  68. class function getnextid: cardinal;
  69. strict protected
  70. fnameval: cardinal;
  71. public
  72. constructor create; reintroduce;
  73. function getname: ansistring; override;
  74. end;
  75. (* !name = !{ type1 value1, ... } *)
  76. tai_llvmnamedmetadatanode = class(tai_llvmbasemetadatanode)
  77. strict protected
  78. fname: ansistring;
  79. function getname: ansistring; override;
  80. public
  81. constructor create(const aName: ansistring);
  82. end;
  83. { reference to a metadata node inside an expression, i.e., !X }
  84. tai_llvmmetadatareftypedconst = class(tai_simple)
  85. strict private
  86. fval: tai_llvmbasemetadatanode;
  87. public
  88. constructor create(_val: tai_llvmbasemetadatanode);
  89. property val: tai_llvmbasemetadatanode read fval;
  90. end;
  91. { @g1 = global i32 0, *!id !value.name* }
  92. tai_llvmmetadatareferenceoperand = class(tai_simple)
  93. strict private
  94. fid: ansistring;
  95. fvalue: tai_llvmmetadatareftypedconst;
  96. public
  97. constructor createreferenceto(const anID: ansistring; aValue: tai_llvmbasemetadatanode);
  98. destructor destroy; override;
  99. property id: ansistring read fid;
  100. property value: tai_llvmmetadatareftypedconst read fvalue;
  101. end;
  102. tllvmspecialmetaitemkind = (
  103. lsmik_boolean,
  104. lsmik_int64,
  105. lsmik_qword,
  106. lsmik_metadataref,
  107. lsmik_string,
  108. { difference with string: not quoted }
  109. lsmik_enum
  110. );
  111. tllvmspecialisedmetaitem = class(tai_simpletypedconst)
  112. private
  113. fitemkind: tllvmspecialmetaitemkind;
  114. fitemname: TSymStr;
  115. public
  116. constructor createboolean(const aitemname: TSymStr; boolval: boolean);
  117. constructor createint64(const aitemname: TSymStr; intval: int64);
  118. constructor createqword(const aitemname: TSymStr; qwval: qword);
  119. constructor createmetadataref(const aitemname: TSymStr; aival: tai_llvmmetadatareftypedconst);
  120. constructor createstring(const aitemname: TSymStr; const stringval: TSymStr);
  121. constructor createenum(const aitemname: TSymStr; const enumval: TSymStr);
  122. property itemname: TSymStr read fitemname;
  123. property itemkind: tllvmspecialmetaitemkind read fitemkind;
  124. end;
  125. tllvmspecialisedmetaitems = array of tllvmspecialisedmetaitem;
  126. { !name = !kindname(field1: value1, ...) }
  127. tai_llvmspecialisedmetadatanode = class(tai_llvmunnamedmetadatanode)
  128. strict private
  129. { identifies name and fieldnames }
  130. fkind: tspecialisedmetadatanodekind;
  131. fnritems: longint;
  132. { adds the item, appropriating its contents (so don't destroy the original
  133. afterwards) }
  134. procedure addemplaceitem(const item: tllvmspecialisedmetaitem);
  135. public
  136. constructor create(aKind: tspecialisedmetadatanodekind);
  137. procedure addvalue(val: tai_abstracttypedconst); override; deprecated 'use addboolean/addinteger/addmetadataref/addstring/addenum';
  138. procedure addboolean(const aitemname: TSymStr; boolval: boolean);
  139. procedure addint64(const aitemname: TSymStr; intval: int64);
  140. procedure addqword(const aitemname: TSymStr; qwval: qword);
  141. procedure addmetadatarefto(const aitemname: TSymStr; aival: tai_llvmbasemetadatanode);
  142. procedure addstring(const aitemname: TSymStr; const stringval: TSymStr);
  143. procedure addenum(const aitemname: TSymStr; const enumval: TSymStr);
  144. property kind: tspecialisedmetadatanodekind read fkind;
  145. function IsDistinct: boolean;
  146. class function isspecialised: boolean; override;
  147. end;
  148. {$push}
  149. {$scopedenums on}
  150. { not clear what the difference is between LineTablesOnly and DebugDirectivesOnly }
  151. tllvmdebugemissionkind = (NoDebug, FullDebug, LineTablesOnly, DebugDirectivesOnly);
  152. {$pop}
  153. tllvmmetadata = class
  154. strict private
  155. class function addstring(const s: TSymstr): TSuperRegister;
  156. class function regtostring(reg: TRegister): TSymStr;
  157. public
  158. class function getstringreg(const s: TSymstr): TRegister;
  159. class function getpcharreg(p: pchar; len: longint): TRegister;
  160. class function getregstring(reg: TRegister): TSymStr;
  161. end;
  162. function llvm_getmetadatareftypedconst(metadata: tai_llvmbasemetadatanode): tai_simpletypedconst;
  163. function llvm_constrainedexceptmodestring: ansistring;
  164. implementation
  165. uses
  166. verbose,globals,cutils,
  167. fmodule,
  168. symdef,
  169. dbgdwarfconst,
  170. aasmdata,aasmllvm;
  171. function llvm_getmetadatareftypedconst(metadata: tai_llvmbasemetadatanode): tai_simpletypedconst;
  172. begin
  173. result:=tai_simpletypedconst.create(llvm_metadatatype, tai_llvmmetadatareftypedconst.create(metadata));
  174. end;
  175. function llvm_constrainedexceptmodestring: ansistring;
  176. begin
  177. if not(cs_opt_fastmath in current_settings.optimizerswitches) then
  178. result:='fpexcept.maytrap'
  179. else
  180. result:='fpexcept.ignore'
  181. end;
  182. /////////////////////////////////////////////////
  183. procedure tai_llvmbasemetadatanode.addvalue(val: tai_abstracttypedconst);
  184. begin
  185. { bypass string merging attempts, as we add tai_strings directly here }
  186. fvalues.add(val);
  187. end;
  188. constructor tai_llvmbasemetadatanode.create;
  189. begin
  190. inherited create(tck_array, llvm_metadatatype);
  191. typ:=ait_llvmmetadatanode;
  192. end;
  193. class function tai_llvmbasemetadatanode.isspecialised: boolean;
  194. begin
  195. result:=false;
  196. end;
  197. class function tai_llvmunnamedmetadatanode.getnextid: cardinal;
  198. begin
  199. result:=tllvmasmdata(current_asmdata).fnextmetaid;
  200. inc(tllvmasmdata(current_asmdata).fnextmetaid);
  201. end;
  202. function tai_llvmunnamedmetadatanode.getname: ansistring;
  203. begin
  204. str(fnameval,result);
  205. end;
  206. constructor tai_llvmunnamedmetadatanode.create;
  207. begin
  208. inherited;
  209. fnameval:=getnextid;
  210. end;
  211. function tai_llvmnamedmetadatanode.getname: ansistring;
  212. begin
  213. result:=fname;
  214. end;
  215. constructor tai_llvmnamedmetadatanode.create(const aName: ansistring);
  216. begin
  217. inherited create;
  218. fname:=aName;
  219. end;
  220. constructor tai_llvmmetadatareftypedconst.create(_val: tai_llvmbasemetadatanode);
  221. begin
  222. inherited create(ait_llvmmetadatareftypedconst);
  223. fval:=_val;
  224. end;
  225. constructor tai_llvmmetadatareferenceoperand.createreferenceto(const anID: ansistring; aValue: tai_llvmbasemetadatanode);
  226. begin
  227. inherited create(ait_llvmmetadatarefoperand);
  228. fid:=anID;
  229. fvalue:=tai_llvmmetadatareftypedconst.create(aValue);
  230. end;
  231. destructor tai_llvmmetadatareferenceoperand.destroy;
  232. begin
  233. fvalue.free;
  234. inherited;
  235. end;
  236. /////////////////////////////////////////////////
  237. constructor tllvmspecialisedmetaitem.createboolean(const aitemname: TSymStr; boolval: boolean);
  238. begin
  239. fitemname:=aitemname;
  240. fitemkind:=lsmik_boolean;
  241. inherited create(llvmbool1type,tai_const.Create_8bit(ord(boolval)));
  242. end;
  243. constructor tllvmspecialisedmetaitem.createint64(const aitemname: TSymStr; intval: int64);
  244. begin
  245. fitemname:=aitemname;
  246. fitemkind:=lsmik_int64;
  247. inherited create(llvmbool1type,tai_const.Create_64bit(intval));
  248. end;
  249. constructor tllvmspecialisedmetaitem.createqword(const aitemname: TSymStr; qwval: qword);
  250. begin
  251. fitemname:=aitemname;
  252. fitemkind:=lsmik_qword;
  253. inherited create(llvmbool1type,tai_const.Create_64bit(int64(qwval)));
  254. end;
  255. constructor tllvmspecialisedmetaitem.createmetadataref(const aitemname: TSymStr; aival: tai_llvmmetadatareftypedconst);
  256. begin
  257. fitemname:=aitemname;
  258. fitemkind:=lsmik_metadataref;
  259. inherited create(llvm_metadatatype,aival);
  260. end;
  261. constructor tllvmspecialisedmetaitem.createstring(const aitemname: TSymStr; const stringval: TSymStr);
  262. begin
  263. fitemname:=aitemname;
  264. fitemkind:=lsmik_string;
  265. inherited create(charpointertype,tai_string.Create(stringval));
  266. end;
  267. constructor tllvmspecialisedmetaitem.createenum(const aitemname: TSymStr; const enumval: TSymStr);
  268. begin
  269. fitemname:=aitemname;
  270. fitemkind:=lsmik_enum;
  271. inherited create(charpointertype,tai_string.Create(enumval));
  272. end;
  273. constructor tai_llvmspecialisedmetadatanode.create(aKind: tspecialisedmetadatanodekind);
  274. begin
  275. inherited create;
  276. fkind:=aKind;
  277. end;
  278. procedure tai_llvmspecialisedmetadatanode.addemplaceitem(const item: tllvmspecialisedmetaitem);
  279. begin
  280. inherited addvalue(item);
  281. end;
  282. procedure tai_llvmspecialisedmetadatanode.addvalue(val: tai_abstracttypedconst);
  283. begin
  284. internalerror(2021121601);
  285. end;
  286. procedure tai_llvmspecialisedmetadatanode.addboolean(const aitemname: TSymStr; boolval: boolean);
  287. var
  288. item: tllvmspecialisedmetaitem;
  289. begin
  290. item:=tllvmspecialisedmetaitem.createboolean(aitemname, boolval);
  291. addemplaceitem(item);
  292. end;
  293. procedure tai_llvmspecialisedmetadatanode.addint64(const aitemname: TSymStr; intval: int64);
  294. var
  295. item: tllvmspecialisedmetaitem;
  296. begin
  297. item:=tllvmspecialisedmetaitem.createint64(aitemname, intval);
  298. addemplaceitem(item);
  299. end;
  300. procedure tai_llvmspecialisedmetadatanode.addqword(const aitemname: TSymStr; qwval: qword);
  301. var
  302. item: tllvmspecialisedmetaitem;
  303. begin
  304. item:=tllvmspecialisedmetaitem.createqword(aitemname, qwval);
  305. addemplaceitem(item);
  306. end;
  307. procedure tai_llvmspecialisedmetadatanode.addmetadatarefto(const aitemname: TSymStr; aival: tai_llvmbasemetadatanode);
  308. var
  309. item: tllvmspecialisedmetaitem;
  310. begin
  311. if assigned(aival) then
  312. item:=tllvmspecialisedmetaitem.createmetadataref(aitemname, tai_llvmmetadatareftypedconst.create(aival))
  313. else
  314. item:=tllvmspecialisedmetaitem.createmetadataref(aitemname, nil);
  315. addemplaceitem(item);
  316. end;
  317. procedure tai_llvmspecialisedmetadatanode.addstring(const aitemname: TSymStr; const stringval: TSymStr);
  318. var
  319. item: tllvmspecialisedmetaitem;
  320. begin
  321. item:=tllvmspecialisedmetaitem.createstring(aitemname, stringval);
  322. addemplaceitem(item);
  323. end;
  324. procedure tai_llvmspecialisedmetadatanode.addenum(const aitemname: TSymStr; const enumval: TSymStr);
  325. var
  326. item: tllvmspecialisedmetaitem;
  327. begin
  328. item:=tllvmspecialisedmetaitem.createenum(aitemname, enumval);
  329. addemplaceitem(item);
  330. end;
  331. function tai_llvmspecialisedmetadatanode.IsDistinct: boolean;
  332. begin
  333. case fkind of
  334. tspecialisedmetadatanodekind.DICompileUnit,
  335. tspecialisedmetadatanodekind.DISubprogram,
  336. tspecialisedmetadatanodekind.DICompositeType,
  337. tspecialisedmetadatanodekind.DILexicalBlock,
  338. tspecialisedmetadatanodekind.DIMacro:
  339. result:=true;
  340. tspecialisedmetadatanodekind.DIFile,
  341. tspecialisedmetadatanodekind.DIBasicType,
  342. tspecialisedmetadatanodekind.DIDerivedType,
  343. tspecialisedmetadatanodekind.DISubrange,
  344. tspecialisedmetadatanodekind.DIEnumerator,
  345. tspecialisedmetadatanodekind.DITemplateTypeParameter,
  346. tspecialisedmetadatanodekind.DITemplateValueParameter,
  347. tspecialisedmetadatanodekind.DINamespace,
  348. tspecialisedmetadatanodekind.DIGlobalVariable,
  349. tspecialisedmetadatanodekind.DILexicalBlockFile,
  350. tspecialisedmetadatanodekind.DILocation,
  351. tspecialisedmetadatanodekind.DILocalVariable,
  352. tspecialisedmetadatanodekind.DIExpression,
  353. tspecialisedmetadatanodekind.DIObjCProperty,
  354. tspecialisedmetadatanodekind.DIImportedEntity,
  355. tspecialisedmetadatanodekind.DISubroutineType,
  356. tspecialisedmetadatanodekind.DIMacroFile:
  357. result:=false;
  358. end;
  359. end;
  360. class function tai_llvmspecialisedmetadatanode.isspecialised: boolean;
  361. begin
  362. result:=true;
  363. end;
  364. /////////////////////////////////////////////////
  365. class function tllvmmetadata.addstring(const s: TSymStr): TSuperRegister;
  366. var
  367. index: longint;
  368. begin
  369. index:=current_module.llvmmetadatastrings.Add(s,nil);
  370. if index>high(result) then
  371. internalerror(2019122806);
  372. result:=index;
  373. end;
  374. class function tllvmmetadata.regtostring(reg: TRegister): TSymStr;
  375. begin
  376. if getregtype(reg)<>R_METADATAREGISTER then
  377. internalerror(2019122807);
  378. if getsubreg(reg)<>R_SUBMETASTRING then
  379. internalerror(2019122808);
  380. result:=current_module.llvmmetadatastrings.NameOfIndex(getsupreg(reg));
  381. end;
  382. class function tllvmmetadata.getstringreg(const s: TSymstr): TRegister;
  383. var
  384. supreg: TSuperRegister;
  385. index: longint;
  386. begin
  387. index:=current_module.llvmmetadatastrings.FindIndexOf(s);
  388. if index<>-1 then
  389. supreg:=index
  390. else
  391. supreg:=addstring(s);
  392. result:=newreg(R_METADATAREGISTER,supreg,R_SUBMETASTRING);
  393. end;
  394. class function tllvmmetadata.getpcharreg(p: pchar; len: longint): TRegister;
  395. var
  396. str: TSymStr;
  397. begin
  398. if len>0 then
  399. begin
  400. setlength(str,len);
  401. move(p[0],str[1],len);
  402. result:=getstringreg(str);
  403. end
  404. else
  405. result:=getstringreg('');
  406. end;
  407. class function tllvmmetadata.getregstring(reg: TRegister): TSymStr;
  408. begin
  409. result:=regtostring(reg);
  410. end;
  411. end.