aasmllvmmetadata.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  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. { !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. if assigned(metadata) then
  174. result:=tai_simpletypedconst.create(llvm_metadatatype, tai_llvmmetadatareftypedconst.create(metadata))
  175. else
  176. result:=nil
  177. end;
  178. function llvm_constrainedexceptmodestring: ansistring;
  179. begin
  180. if not(cs_opt_fastmath in current_settings.optimizerswitches) then
  181. result:='fpexcept.maytrap'
  182. else
  183. result:='fpexcept.ignore'
  184. end;
  185. /////////////////////////////////////////////////
  186. procedure tai_llvmbasemetadatanode.addvalue(val: tai_abstracttypedconst);
  187. begin
  188. { bypass string merging attempts, as we add tai_strings directly here }
  189. fvalues.add(val);
  190. end;
  191. constructor tai_llvmbasemetadatanode.create;
  192. begin
  193. inherited create(tck_array, llvm_metadatatype);
  194. typ:=ait_llvmmetadatanode;
  195. end;
  196. class function tai_llvmbasemetadatanode.isspecialised: boolean;
  197. begin
  198. result:=false;
  199. end;
  200. class function tai_llvmunnamedmetadatanode.getnextid: cardinal;
  201. begin
  202. result:=tllvmasmdata(current_asmdata).fnextmetaid;
  203. inc(tllvmasmdata(current_asmdata).fnextmetaid);
  204. end;
  205. function tai_llvmunnamedmetadatanode.getname: ansistring;
  206. begin
  207. str(fnameval,result);
  208. end;
  209. constructor tai_llvmunnamedmetadatanode.create;
  210. begin
  211. inherited;
  212. fnameval:=getnextid;
  213. end;
  214. function tai_llvmnamedmetadatanode.getname: ansistring;
  215. begin
  216. result:=fname;
  217. end;
  218. constructor tai_llvmnamedmetadatanode.create(const aName: ansistring);
  219. begin
  220. inherited create;
  221. fname:=aName;
  222. end;
  223. constructor tai_llvmmetadatareftypedconst.create(_val: tai_llvmbasemetadatanode);
  224. begin
  225. inherited create(ait_llvmmetadatareftypedconst);
  226. fval:=_val;
  227. end;
  228. constructor tai_llvmmetadatareferenceoperand.createreferenceto(const anID: ansistring; aValue: tai_llvmbasemetadatanode);
  229. begin
  230. inherited create(ait_llvmmetadatarefoperand);
  231. fid:=anID;
  232. fvalue:=tai_llvmmetadatareftypedconst.create(aValue);
  233. end;
  234. destructor tai_llvmmetadatareferenceoperand.destroy;
  235. begin
  236. fvalue.free;
  237. inherited;
  238. end;
  239. /////////////////////////////////////////////////
  240. constructor tllvmspecialisedmetaitem.createboolean(const aitemname: TSymStr; boolval: boolean);
  241. begin
  242. fitemname:=aitemname;
  243. fitemkind:=lsmik_boolean;
  244. inherited create(llvmbool1type,tai_const.Create_8bit(ord(boolval)));
  245. end;
  246. constructor tllvmspecialisedmetaitem.createint64(const aitemname: TSymStr; intval: int64);
  247. begin
  248. fitemname:=aitemname;
  249. fitemkind:=lsmik_int64;
  250. inherited create(llvmbool1type,tai_const.Create_64bit(intval));
  251. end;
  252. constructor tllvmspecialisedmetaitem.createqword(const aitemname: TSymStr; qwval: qword);
  253. begin
  254. fitemname:=aitemname;
  255. fitemkind:=lsmik_qword;
  256. inherited create(llvmbool1type,tai_const.Create_64bit(int64(qwval)));
  257. end;
  258. constructor tllvmspecialisedmetaitem.createmetadataref(const aitemname: TSymStr; aival: tai_llvmmetadatareftypedconst);
  259. begin
  260. fitemname:=aitemname;
  261. fitemkind:=lsmik_metadataref;
  262. inherited create(llvm_metadatatype,aival);
  263. end;
  264. constructor tllvmspecialisedmetaitem.createstring(const aitemname: TSymStr; const stringval: TSymStr);
  265. begin
  266. fitemname:=aitemname;
  267. fitemkind:=lsmik_string;
  268. inherited create(charpointertype,tai_string.Create(stringval));
  269. end;
  270. constructor tllvmspecialisedmetaitem.createenum(const aitemname: TSymStr; const enumval: TSymStr);
  271. begin
  272. fitemname:=aitemname;
  273. fitemkind:=lsmik_enum;
  274. inherited create(charpointertype,tai_string.Create(enumval));
  275. end;
  276. constructor tai_llvmspecialisedmetadatanode.create(aKind: tspecialisedmetadatanodekind);
  277. begin
  278. inherited create;
  279. fkind:=aKind;
  280. end;
  281. procedure tai_llvmspecialisedmetadatanode.addemplaceitem(const item: tllvmspecialisedmetaitem);
  282. begin
  283. inherited addvalue(item);
  284. end;
  285. procedure tai_llvmspecialisedmetadatanode.addvalue(val: tai_abstracttypedconst);
  286. begin
  287. internalerror(2021121601);
  288. end;
  289. procedure tai_llvmspecialisedmetadatanode.addboolean(const aitemname: TSymStr; boolval: boolean);
  290. var
  291. item: tllvmspecialisedmetaitem;
  292. begin
  293. item:=tllvmspecialisedmetaitem.createboolean(aitemname, boolval);
  294. addemplaceitem(item);
  295. end;
  296. procedure tai_llvmspecialisedmetadatanode.addint64(const aitemname: TSymStr; intval: int64);
  297. var
  298. item: tllvmspecialisedmetaitem;
  299. begin
  300. item:=tllvmspecialisedmetaitem.createint64(aitemname, intval);
  301. addemplaceitem(item);
  302. end;
  303. procedure tai_llvmspecialisedmetadatanode.addqword(const aitemname: TSymStr; qwval: qword);
  304. var
  305. item: tllvmspecialisedmetaitem;
  306. begin
  307. item:=tllvmspecialisedmetaitem.createqword(aitemname, qwval);
  308. addemplaceitem(item);
  309. end;
  310. procedure tai_llvmspecialisedmetadatanode.addmetadatarefto(const aitemname: TSymStr; aival: tai_llvmbasemetadatanode);
  311. var
  312. item: tllvmspecialisedmetaitem;
  313. begin
  314. if assigned(aival) then
  315. item:=tllvmspecialisedmetaitem.createmetadataref(aitemname, tai_llvmmetadatareftypedconst.create(aival))
  316. else
  317. item:=tllvmspecialisedmetaitem.createmetadataref(aitemname, nil);
  318. addemplaceitem(item);
  319. end;
  320. procedure tai_llvmspecialisedmetadatanode.addstring(const aitemname: TSymStr; const stringval: TSymStr);
  321. var
  322. item: tllvmspecialisedmetaitem;
  323. begin
  324. item:=tllvmspecialisedmetaitem.createstring(aitemname, stringval);
  325. addemplaceitem(item);
  326. end;
  327. procedure tai_llvmspecialisedmetadatanode.addenum(const aitemname: TSymStr; const enumval: TSymStr);
  328. var
  329. item: tllvmspecialisedmetaitem;
  330. begin
  331. item:=tllvmspecialisedmetaitem.createenum(aitemname, enumval);
  332. addemplaceitem(item);
  333. end;
  334. function tai_llvmspecialisedmetadatanode.IsDistinct: boolean;
  335. begin
  336. case fkind of
  337. tspecialisedmetadatanodekind.DICompileUnit,
  338. tspecialisedmetadatanodekind.DISubprogram,
  339. tspecialisedmetadatanodekind.DIGlobalVariable,
  340. tspecialisedmetadatanodekind.DICompositeType,
  341. tspecialisedmetadatanodekind.DILexicalBlock,
  342. tspecialisedmetadatanodekind.DIMacro:
  343. result:=true;
  344. tspecialisedmetadatanodekind.DIFile,
  345. tspecialisedmetadatanodekind.DIBasicType,
  346. tspecialisedmetadatanodekind.DIDerivedType,
  347. tspecialisedmetadatanodekind.DISubrange,
  348. tspecialisedmetadatanodekind.DIEnumerator,
  349. tspecialisedmetadatanodekind.DITemplateTypeParameter,
  350. tspecialisedmetadatanodekind.DITemplateValueParameter,
  351. tspecialisedmetadatanodekind.DINamespace,
  352. tspecialisedmetadatanodekind.DIGlobalVariableExpression,
  353. tspecialisedmetadatanodekind.DILexicalBlockFile,
  354. tspecialisedmetadatanodekind.DILocation,
  355. tspecialisedmetadatanodekind.DILocalVariable,
  356. tspecialisedmetadatanodekind.DIExpression,
  357. tspecialisedmetadatanodekind.DIObjCProperty,
  358. tspecialisedmetadatanodekind.DIImportedEntity,
  359. tspecialisedmetadatanodekind.DISubroutineType,
  360. tspecialisedmetadatanodekind.DIMacroFile:
  361. result:=false;
  362. end;
  363. end;
  364. class function tai_llvmspecialisedmetadatanode.isspecialised: boolean;
  365. begin
  366. result:=true;
  367. end;
  368. /////////////////////////////////////////////////
  369. class function tllvmmetadata.addstring(const s: TSymStr): TSuperRegister;
  370. var
  371. index: longint;
  372. begin
  373. index:=current_module.llvmmetadatastrings.Add(s,nil);
  374. if index>high(result) then
  375. internalerror(2019122806);
  376. result:=index;
  377. end;
  378. class function tllvmmetadata.regtostring(reg: TRegister): TSymStr;
  379. begin
  380. if getregtype(reg)<>R_METADATAREGISTER then
  381. internalerror(2019122807);
  382. if getsubreg(reg)<>R_SUBMETASTRING then
  383. internalerror(2019122808);
  384. result:=current_module.llvmmetadatastrings.NameOfIndex(getsupreg(reg));
  385. end;
  386. class function tllvmmetadata.getstringreg(const s: TSymstr): TRegister;
  387. var
  388. supreg: TSuperRegister;
  389. index: longint;
  390. begin
  391. index:=current_module.llvmmetadatastrings.FindIndexOf(s);
  392. if index<>-1 then
  393. supreg:=index
  394. else
  395. supreg:=addstring(s);
  396. result:=newreg(R_METADATAREGISTER,supreg,R_SUBMETASTRING);
  397. end;
  398. class function tllvmmetadata.getpcharreg(p: pchar; len: longint): TRegister;
  399. var
  400. str: TSymStr;
  401. begin
  402. if len>0 then
  403. begin
  404. setlength(str,len);
  405. move(p[0],str[1],len);
  406. result:=getstringreg(str);
  407. end
  408. else
  409. result:=getstringreg('');
  410. end;
  411. class function tllvmmetadata.getregstring(reg: TRegister): TSymStr;
  412. begin
  413. result:=regtostring(reg);
  414. end;
  415. end.