aasmllvmmetadata.pas 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  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. type
  27. tspecialisedmetadatanodekind = (
  28. smeta_DIFile,
  29. smeta_DIBasicType,
  30. smeta_DISubroutineType,
  31. smeta_DIDerivedType,
  32. smeta_DICompositeType,
  33. smeta_DISubrange,
  34. smeta_DIEnumerator,
  35. smeta_DITemplateTypeParameter,
  36. smeta_DITemplateValueParameter,
  37. smeta_DINamespace,
  38. smeta_DIGlobalVariable,
  39. smeta_DISubprogram,
  40. smeta_DILexicalBlock,
  41. smeta_DILexicalBlockFile,
  42. smeta_DILocation,
  43. smeta_DILocalVariable,
  44. smeta_DIExpression,
  45. smeta_DIObjCProperty,
  46. smeta_DIImportedEntity,
  47. smeta_DIMacro,
  48. smeta_DIMacroFile
  49. );
  50. // represented by a tai_simpletypedconst() with inside a metadata struct,
  51. // or as a metadata register (for parameters)
  52. // tai_llvmmetadatastring = class
  53. tai_llvmbasemetadatanode = class abstract(tai_aggregatetypedconst)
  54. strict protected
  55. function getname: ansistring; virtual; abstract;
  56. public
  57. procedure addvalue(val: tai_abstracttypedconst); override;
  58. property name: ansistring read getname;
  59. constructor create; reintroduce;
  60. end;
  61. (* !0 = !{ type1 value1, ... } *)
  62. tai_llvmunnamedmetadatanode = class(tai_llvmbasemetadatanode)
  63. strict private class var
  64. snextid: TSuperRegister;
  65. class function getnextid: TSuperRegister;
  66. strict protected
  67. fnameval: TSuperRegister;
  68. public
  69. constructor create; reintroduce;
  70. function getname: ansistring; override;
  71. end;
  72. (* !name = !{ type1 value1, ... } *)
  73. tai_llvmnamedmetadatanode = class(tai_llvmbasemetadatanode)
  74. strict protected
  75. fname: ansistring;
  76. function getname: ansistring; override;
  77. public
  78. constructor create(const aName: ansistring);
  79. end;
  80. tai_llvmmetadatareftypedconst = class(tai_simple)
  81. strict private
  82. fval: tai_llvmbasemetadatanode;
  83. public
  84. constructor create(_val: tai_llvmbasemetadatanode);
  85. property val: tai_llvmbasemetadatanode read fval;
  86. end;
  87. { @g1 = global i32 0, *!id !value.name* }
  88. tai_llvmmetadatareferenceoperand = class(tai_simple)
  89. strict private
  90. fid: ansistring;
  91. fvalue: tai_llvmbasemetadatanode;
  92. public
  93. constructor create(const anID: ansistring; aValue: tai_llvmbasemetadatanode);
  94. property id: ansistring read fid;
  95. property value: tai_llvmbasemetadatanode read fvalue;
  96. end;
  97. { !name = !kindname(field1: value1, ...) }
  98. tai_llvmspecialisedmetadatanode = class(tai_llvmunnamedmetadatanode)
  99. { identifies name and fieldnames }
  100. kind: tspecialisedmetadatanodekind;
  101. end;
  102. tllvmmetadata = class
  103. strict private
  104. class function addstring(const s: TSymstr): TSuperRegister;
  105. class function regtostring(reg: TRegister): TSymStr;
  106. public
  107. class function getstringreg(const s: TSymstr): TRegister;
  108. class function getpcharreg(p: pchar; len: longint): TRegister;
  109. class function getregstring(reg: TRegister): TSymStr;
  110. end;
  111. function llvm_getmetadatareftypedconst(metadata: tai_llvmbasemetadatanode): tai_simpletypedconst;
  112. function llvm_constrainedexceptmodestring: ansistring;
  113. implementation
  114. uses
  115. verbose,globals,
  116. fmodule,
  117. symdef;
  118. function llvm_getmetadatareftypedconst(metadata: tai_llvmbasemetadatanode): tai_simpletypedconst;
  119. begin
  120. result:=tai_simpletypedconst.create(llvm_metadatatype, tai_llvmmetadatareftypedconst.create(metadata));
  121. end;
  122. function llvm_constrainedexceptmodestring: ansistring;
  123. begin
  124. if not(cs_opt_fastmath in current_settings.optimizerswitches) then
  125. result:='fpexcept.maytrap'
  126. else
  127. result:='fpexcept.ignore'
  128. end;
  129. procedure tai_llvmbasemetadatanode.addvalue(val: tai_abstracttypedconst);
  130. begin
  131. { bypass string merging attempts, as we add tai_strings directly here }
  132. fvalues.add(val);
  133. end;
  134. constructor tai_llvmbasemetadatanode.create;
  135. begin
  136. inherited create(tck_array, llvm_metadatatype);
  137. typ:=ait_llvmmetadatanode;
  138. end;
  139. class function tai_llvmunnamedmetadatanode.getnextid: TSuperRegister;
  140. begin
  141. result:=snextid;
  142. inc(snextid);
  143. end;
  144. function tai_llvmunnamedmetadatanode.getname: ansistring;
  145. begin
  146. str(fnameval,result);
  147. end;
  148. constructor tai_llvmunnamedmetadatanode.create;
  149. begin
  150. inherited;
  151. fnameval:=getnextid;
  152. end;
  153. function tai_llvmnamedmetadatanode.getname: ansistring;
  154. begin
  155. result:=fname;
  156. end;
  157. constructor tai_llvmnamedmetadatanode.create(const aName: ansistring);
  158. begin
  159. inherited create;
  160. fname:=aName;
  161. end;
  162. constructor tai_llvmmetadatareftypedconst.create(_val: tai_llvmbasemetadatanode);
  163. begin
  164. inherited create(ait_llvmmetadatareftypedconst);
  165. fval:=_val;
  166. end;
  167. constructor tai_llvmmetadatareferenceoperand.create(const anID: ansistring; aValue: tai_llvmbasemetadatanode);
  168. begin
  169. inherited create(ait_llvmmetadatarefoperand);
  170. fid:=anID;
  171. fvalue:=aValue;
  172. end;
  173. /////////////////////////////////////////////////
  174. class function tllvmmetadata.addstring(const s: TSymStr): TSuperRegister;
  175. var
  176. index: longint;
  177. begin
  178. index:=current_module.llvmmetadatastrings.Add(s,nil);
  179. if index>high(result) then
  180. internalerror(2019122806);
  181. result:=index;
  182. end;
  183. class function tllvmmetadata.regtostring(reg: TRegister): TSymStr;
  184. begin
  185. if getregtype(reg)<>R_METADATAREGISTER then
  186. internalerror(2019122807);
  187. if getsubreg(reg)<>R_SUBMETASTRING then
  188. internalerror(2019122808);
  189. result:=current_module.llvmmetadatastrings.NameOfIndex(getsupreg(reg));
  190. end;
  191. class function tllvmmetadata.getstringreg(const s: TSymstr): TRegister;
  192. var
  193. supreg: TSuperRegister;
  194. index: longint;
  195. begin
  196. index:=current_module.llvmmetadatastrings.FindIndexOf(s);
  197. if index<>-1 then
  198. supreg:=index
  199. else
  200. supreg:=addstring(s);
  201. result:=newreg(R_METADATAREGISTER,supreg,R_SUBMETASTRING);
  202. end;
  203. class function tllvmmetadata.getpcharreg(p: pchar; len: longint): TRegister;
  204. var
  205. str: TSymStr;
  206. begin
  207. if len>0 then
  208. begin
  209. setlength(str,len);
  210. move(p[0],str[1],len);
  211. result:=getstringreg(str);
  212. end
  213. else
  214. result:=getstringreg('');
  215. end;
  216. class function tllvmmetadata.getregstring(reg: TRegister): TSymStr;
  217. begin
  218. result:=regtostring(reg);
  219. end;
  220. end.