2
0

nllvmcon.pas 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. {
  2. Copyright (c) 2013 by Jonas Maebe, member of the Free Pascal Compiler
  3. development team
  4. Generate llvm bitcode for constants
  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 nllvmcon;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. symtype,
  23. node,ncgcon;
  24. type
  25. tllvmrealconstnode = class(tcgrealconstnode)
  26. function pass_1 : tnode;override;
  27. procedure pass_generate_code;override;
  28. end;
  29. tllvmstringconstnode = class(tcgstringconstnode)
  30. constructor createpchar(s: pchar; l: longint; def: tdef); override;
  31. function pass_typecheck: tnode; override;
  32. function pass_1: tnode; override;
  33. procedure pass_generate_code; override;
  34. protected
  35. procedure load_dynstring(const strpointerdef: tdef; const elementdef: tdef; const winlikewidestring: boolean); override;
  36. end;
  37. implementation
  38. uses
  39. globtype,globals,verbose,cutils,
  40. symbase,symtable,symconst,symdef,symsym,defutil,
  41. aasmbase,aasmdata,aasmcnst,
  42. ncon,
  43. llvmbase,aasmllvm,aasmllvmmetadata,hlcgobj,
  44. cgbase,cgutils,
  45. cpubase;
  46. {*****************************************************************************
  47. tllvmstringconstnode
  48. *****************************************************************************}
  49. constructor tllvmstringconstnode.createpchar(s: pchar; l: longint; def: tdef);
  50. begin
  51. inherited;
  52. if def=llvm_metadatatype then
  53. begin
  54. { astringdef is only used if the constant type is ansitring }
  55. cst_type:=cst_ansistring;
  56. astringdef:=def;
  57. end;
  58. end;
  59. function tllvmstringconstnode.pass_typecheck: tnode;
  60. begin
  61. if astringdef<>llvm_metadatatype then
  62. begin
  63. result:=inherited;
  64. exit;
  65. end;
  66. resultdef:=llvm_metadatatype;
  67. result:=nil;
  68. end;
  69. function tllvmstringconstnode.pass_1: tnode;
  70. begin
  71. if astringdef<>llvm_metadatatype then
  72. begin
  73. result:=inherited;
  74. exit;
  75. end;
  76. expectloc:=LOC_CREGISTER;
  77. result:=nil;
  78. end;
  79. procedure tllvmstringconstnode.pass_generate_code;
  80. var
  81. datadef, resptrdef: tdef;
  82. hreg: tregister;
  83. begin
  84. if astringdef=llvm_metadatatype then
  85. begin
  86. location_reset(location,LOC_CREGISTER,OS_ADDR);
  87. location.register:=tllvmmetadata.getpcharreg(value_str,len);
  88. exit;
  89. end;
  90. inherited pass_generate_code;
  91. if cst_type in [cst_conststring,cst_shortstring] then
  92. begin
  93. if location.loc<>LOC_CREFERENCE then
  94. internalerror(2014071202);
  95. case cst_type of
  96. cst_conststring:
  97. { this kind of string const is used both for array of char
  98. constants (-> excludes terminating #0) and pchars (-> includes
  99. terminating #0). The resultdef excludes the #0 while the data
  100. includes it -> insert typecast from datadef to resultdef }
  101. datadef:=carraydef.getreusable(cansichartype,len+1);
  102. cst_shortstring:
  103. { the resultdef of the string constant is the type of the
  104. string to which it is assigned, which can be longer or shorter
  105. than the length of the string itself -> typecast it to the
  106. correct string type }
  107. datadef:=carraydef.getreusable(cansichartype,min(len,255)+1);
  108. else
  109. internalerror(2014071203);
  110. end;
  111. { get address of array as pchar }
  112. resptrdef:=cpointerdef.getreusable(resultdef);
  113. hreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,resptrdef);
  114. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,datadef,resptrdef,location.reference,hreg);
  115. hlcg.reference_reset_base(location.reference,resptrdef,hreg,0,location.reference.temppos,location.reference.alignment,location.reference.volatility);
  116. end;
  117. end;
  118. procedure tllvmstringconstnode.load_dynstring(const strpointerdef: tdef; const elementdef: tdef; const winlikewidestring: boolean);
  119. var
  120. stringtype: tstringtype;
  121. strrecdef: trecorddef;
  122. offset: pint;
  123. field: tfieldvarsym;
  124. llvmfield: tllvmshadowsymtableentry;
  125. dataptrdef: tdef;
  126. reg: tregister;
  127. href: treference;
  128. begin
  129. case cst_type of
  130. cst_ansistring:
  131. stringtype:=st_ansistring;
  132. cst_unicodestring:
  133. stringtype:=st_unicodestring;
  134. cst_widestring:
  135. stringtype:=st_widestring;
  136. else
  137. internalerror(2014040804);
  138. end;
  139. { get the recorddef for this string constant }
  140. strrecdef:=ctai_typedconstbuilder.get_dynstring_rec(stringtype,winlikewidestring,len);
  141. { offset in the record of the the string data }
  142. offset:=ctai_typedconstbuilder.get_string_symofs(stringtype,winlikewidestring);
  143. { field corresponding to this offset }
  144. field:=trecordsymtable(strrecdef.symtable).findfieldbyoffset(offset);
  145. llvmfield:=trecordsymtable(strrecdef.symtable).llvmst[field];
  146. if llvmfield.fieldoffset<>field.fieldoffset then
  147. internalerror(2015061001);
  148. { pointerdef to the string data array }
  149. dataptrdef:=cpointerdef.getreusable(field.vardef);
  150. { load the address of the string data }
  151. reg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,dataptrdef);
  152. reference_reset_symbol(href,lab_str,0,const_align(strpointerdef.size),[]);
  153. current_asmdata.CurrAsmList.concat(
  154. taillvm.getelementptr_reg_size_ref_size_const(reg,cpointerdef.getreusable(strrecdef),href,
  155. s32inttype,field.llvmfieldnr,true));
  156. { convert into a pointer to the individual elements }
  157. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,dataptrdef,strpointerdef,reg,location.register);
  158. end;
  159. {*****************************************************************************
  160. tllvmrealconstnode
  161. *****************************************************************************}
  162. function tllvmrealconstnode.pass_1 : tnode;
  163. begin
  164. result:=nil;
  165. expectloc:=LOC_FPUREGISTER;
  166. end;
  167. procedure tllvmrealconstnode.pass_generate_code;
  168. begin
  169. { llvm supports floating point constants directly }
  170. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  171. location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
  172. case tfloatdef(resultdef).floattype of
  173. s32real,s64real:
  174. current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_fpconst_size(la_bitcast,location.register,resultdef,value_real,resultdef));
  175. { comp and currency are handled as int64 at the llvm level }
  176. s64comp:
  177. { sc80floattype instead of resultdef, see comment in thlcgllvm.a_loadfpu_ref_reg }
  178. current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_const_size(la_sitofp,location.register,s64inttype,trunc(value_real),sc80floattype));
  179. s64currency:
  180. { sc80floattype instead of resultdef, see comment in thlcgllvm.a_loadfpu_ref_reg }
  181. current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_const_size(la_sitofp,location.register,s64inttype,round(value_real),sc80floattype));
  182. {$ifdef cpuextended}
  183. s80real,sc80real:
  184. current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_fpconst80_size(la_bitcast,location.register,resultdef,value_real,resultdef));
  185. {$endif cpuextended}
  186. else
  187. internalerror(2013102501);
  188. end;
  189. end;
  190. begin
  191. cstringconstnode:=tllvmstringconstnode;
  192. crealconstnode:=tllvmrealconstnode;
  193. end.