aasmllvmmetadata.pas 15 KB

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