2
0

nllvmcon.pas 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  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. procedure pass_generate_code; override;
  31. protected
  32. procedure load_dynstring(const strpointerdef: tdef; const elementdef: tdef; const winlikewidestring: boolean); override;
  33. end;
  34. implementation
  35. uses
  36. globtype,globals,verbose,cutils,
  37. symbase,symtable,symconst,symdef,symsym,defutil,
  38. aasmdata,aasmcnst,
  39. ncon,
  40. llvmbase,aasmllvm,hlcgobj,
  41. cgbase,cgutils;
  42. {*****************************************************************************
  43. tllvmstringconstnode
  44. *****************************************************************************}
  45. procedure tllvmstringconstnode.pass_generate_code;
  46. var
  47. datadef, resptrdef: tdef;
  48. hreg: tregister;
  49. begin
  50. inherited pass_generate_code;
  51. if cst_type in [cst_conststring,cst_shortstring] then
  52. begin
  53. if location.loc<>LOC_CREFERENCE then
  54. internalerror(2014071202);
  55. case cst_type of
  56. cst_conststring:
  57. { this kind of string const is used both for array of char
  58. constants (-> excludes terminating #0) and pchars (-> includes
  59. terminating #0). The resultdef excludes the #0 while the data
  60. includes it -> insert typecast from datadef to resultdef }
  61. datadef:=carraydef.getreusable(cansichartype,len+1);
  62. cst_shortstring:
  63. { the resultdef of the string constant is the type of the
  64. string to which it is assigned, which can be longer or shorter
  65. than the length of the string itself -> typecast it to the
  66. correct string type }
  67. datadef:=carraydef.getreusable(cansichartype,min(len,255)+1);
  68. else
  69. internalerror(2014071203);
  70. end;
  71. { get address of array as pchar }
  72. resptrdef:=cpointerdef.getreusable(resultdef);
  73. hreg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,resptrdef);
  74. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,datadef,resptrdef,location.reference,hreg);
  75. hlcg.reference_reset_base(location.reference,resptrdef,hreg,0,location.reference.temppos,location.reference.alignment,location.reference.volatility);
  76. end;
  77. end;
  78. procedure tllvmstringconstnode.load_dynstring(const strpointerdef: tdef; const elementdef: tdef; const winlikewidestring: boolean);
  79. var
  80. stringtype: tstringtype;
  81. strrecdef: trecorddef;
  82. offset: pint;
  83. field: tfieldvarsym;
  84. llvmfield: tllvmshadowsymtableentry;
  85. dataptrdef: tdef;
  86. reg: tregister;
  87. href: treference;
  88. begin
  89. case cst_type of
  90. cst_ansistring:
  91. stringtype:=st_ansistring;
  92. cst_unicodestring:
  93. stringtype:=st_unicodestring;
  94. cst_widestring:
  95. stringtype:=st_widestring;
  96. else
  97. internalerror(2014040804);
  98. end;
  99. { get the recorddef for this string constant }
  100. strrecdef:=ctai_typedconstbuilder.get_dynstring_rec(stringtype,winlikewidestring,len);
  101. { offset in the record of the the string data }
  102. offset:=ctai_typedconstbuilder.get_string_symofs(stringtype,winlikewidestring);
  103. { field corresponding to this offset }
  104. field:=trecordsymtable(strrecdef.symtable).findfieldbyoffset(offset);
  105. llvmfield:=trecordsymtable(strrecdef.symtable).llvmst[field];
  106. if llvmfield.fieldoffset<>field.fieldoffset then
  107. internalerror(2015061001);
  108. { pointerdef to the string data array }
  109. dataptrdef:=cpointerdef.getreusable(field.vardef);
  110. { load the address of the string data }
  111. reg:=hlcg.getaddressregister(current_asmdata.CurrAsmList,dataptrdef);
  112. reference_reset_symbol(href,lab_str,0,const_align(strpointerdef.size),[]);
  113. current_asmdata.CurrAsmList.concat(
  114. taillvm.getelementptr_reg_size_ref_size_const(reg,cpointerdef.getreusable(strrecdef),href,
  115. s32inttype,field.llvmfieldnr,true));
  116. { convert into a pointer to the individual elements }
  117. hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,dataptrdef,strpointerdef,reg,location.register);
  118. end;
  119. {*****************************************************************************
  120. tllvmrealconstnode
  121. *****************************************************************************}
  122. function tllvmrealconstnode.pass_1 : tnode;
  123. begin
  124. result:=nil;
  125. expectloc:=LOC_FPUREGISTER;
  126. end;
  127. procedure tllvmrealconstnode.pass_generate_code;
  128. begin
  129. { llvm supports floating point constants directly }
  130. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  131. location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
  132. case tfloatdef(resultdef).floattype of
  133. s32real,s64real:
  134. current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_fpconst_size(la_bitcast,location.register,resultdef,value_real,resultdef));
  135. { comp and currency are handled as int64 at the llvm level }
  136. s64comp,
  137. s64currency:
  138. { sc80floattype instead of resultdef, see comment in thlcgllvm.a_loadfpu_ref_reg }
  139. current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_const_size(la_sitofp,location.register,s64inttype,trunc(value_real),sc80floattype));
  140. {$ifdef cpuextended}
  141. s80real,sc80real:
  142. current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_fpconst80_size(la_bitcast,location.register,resultdef,value_real,resultdef));
  143. {$endif cpuextended}
  144. else
  145. internalerror(2013102501);
  146. end;
  147. end;
  148. begin
  149. cstringconstnode:=tllvmstringconstnode;
  150. crealconstnode:=tllvmrealconstnode;
  151. end.