aasmllvmmetadata.pas 15 KB

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