nllvminl.pas 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. {
  2. Copyright (c) 2014 by Jonas Maebe
  3. Generate LLVM bytecode for inline nodes
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit nllvminl;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,
  22. ncginl;
  23. type
  24. tllvminlinenode = class(tcginlinenode)
  25. protected
  26. function first_get_frame: tnode; override;
  27. function first_abs_real: tnode; override;
  28. function first_sqr_real: tnode; override;
  29. public
  30. procedure second_length; override;
  31. procedure second_sqr_real; override;
  32. end;
  33. implementation
  34. uses
  35. verbose,globtype,constexp,
  36. aasmbase, aasmdata,
  37. symtype,symdef,defutil,
  38. nutils,nadd,nbas,ncal,ncon,nflw,ninl,nld,nmat,
  39. pass_2,
  40. cgbase,cgutils,tgobj,hlcgobj,
  41. cpubase,
  42. llvmbase,aasmllvm;
  43. function tllvminlinenode.first_get_frame: tnode;
  44. begin
  45. result:=ccallnode.createintern('llvm_frameaddress',
  46. ccallparanode.create(genintconstnode(0),nil));
  47. end;
  48. { in general, generate regular expression rather than intrinsics: according
  49. to the "Performance Tips for Frontend Authors", "The optimizer is quite
  50. good at reasoning about general control flow and arithmetic, it is not
  51. anywhere near as strong at reasoning about the various intrinsics. If
  52. profitable for code generation purposes, the optimizer will likely form
  53. the intrinsics itself late in the optimization pipeline." }
  54. function tllvminlinenode.first_abs_real: tnode;
  55. var
  56. lefttemp,
  57. resulttemp: ttempcreatenode;
  58. stat: tstatementnode;
  59. begin
  60. result:=internalstatements(stat);
  61. lefttemp:=ctempcreatenode.create(left.resultdef,left.resultdef.size,tt_persistent,true);
  62. { assigned twice -> will be spilled if put in register }
  63. resulttemp:=ctempcreatenode.create(resultdef,resultdef.size,tt_persistent,false);
  64. addstatement(stat,lefttemp);
  65. addstatement(stat,resulttemp);
  66. { lefttemp:=left }
  67. addstatement(stat,
  68. cassignmentnode.create(ctemprefnode.create(lefttemp),left)
  69. );
  70. { if lefttemp>=0 then
  71. resulttemp:=lefttemp
  72. else
  73. resulttemp:=-lefttemp
  74. }
  75. addstatement(stat,
  76. cifnode.create(
  77. caddnode.create(
  78. gten,
  79. ctemprefnode.create(lefttemp),
  80. crealconstnode.create(0.0,left.resultdef)
  81. ),
  82. cassignmentnode.create(
  83. ctemprefnode.create(resulttemp),
  84. ctemprefnode.create(lefttemp)
  85. ),
  86. cassignmentnode.create(
  87. ctemprefnode.create(resulttemp),
  88. cunaryminusnode.create(ctemprefnode.create(lefttemp))
  89. )
  90. )
  91. );
  92. addstatement(stat,ctempdeletenode.create(lefttemp));
  93. addstatement(stat,ctempdeletenode.create_normal_temp(resulttemp));
  94. { return resulttemp }
  95. addstatement(stat,ctemprefnode.create(resulttemp));
  96. { reused }
  97. left:=nil;
  98. end;
  99. function tllvminlinenode.first_sqr_real: tnode;
  100. begin
  101. result:=nil;
  102. if use_vectorfpu(left.resultdef) then
  103. expectloc:=LOC_MMREGISTER
  104. else
  105. expectloc:=LOC_FPUREGISTER;
  106. end;
  107. procedure tllvminlinenode.second_length;
  108. var
  109. lengthlab, nillab: tasmlabel;
  110. hregister: tregister;
  111. href, tempref: treference;
  112. lendef: tdef;
  113. begin
  114. secondpass(left);
  115. if is_shortstring(left.resultdef) then
  116. begin
  117. if not(left.location.loc in [LOC_REFERENCE,LOC_CREFERENCE]) then
  118. internalerror(2014080806);
  119. { typecast the shortstring reference into a length byte reference }
  120. location_reset_ref(location,left.location.loc,def_cgsize(resultdef),left.location.reference.alignment);
  121. hregister:=hlcg.getaddressregister(current_asmdata.CurrAsmList,cpointerdef.getreusable(resultdef));
  122. hlcg.a_loadaddr_ref_reg(current_asmdata.CurrAsmList,left.resultdef,cpointerdef.getreusable(resultdef),left.location.reference,hregister);
  123. hlcg.reference_reset_base(location.reference,cpointerdef.getreusable(resultdef),hregister,0,left.location.reference.alignment);
  124. end
  125. else
  126. begin
  127. tg.gethltemp(current_asmdata.CurrAsmList,resultdef,resultdef.size,tt_normal,tempref);
  128. { length in ansi/wide strings and high in dynamic arrays is at offset
  129. -sizeof(sizeint), for widestrings it's at -4 }
  130. if is_widestring(left.resultdef) then
  131. lendef:=u32inttype
  132. else
  133. lendef:=ossinttype;
  134. hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,
  135. left.resultdef,cpointerdef.getreusable(lendef),true);
  136. current_asmdata.getjumplabel(nillab);
  137. current_asmdata.getjumplabel(lengthlab);
  138. hlcg.a_cmp_const_reg_label(current_asmdata.CurrAsmList,cpointerdef.getreusable(lendef),OC_EQ,0,left.location.register,nillab);
  139. hlcg.reference_reset_base(href,cpointerdef.getreusable(lendef),left.location.register,-lendef.size,lendef.alignment);
  140. hregister:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  141. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,lendef,resultdef,href,hregister);
  142. if is_widestring(left.resultdef) then
  143. hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_SHR,resultdef,1,hregister);
  144. { Dynamic arrays do not have their length attached but their maximum index }
  145. if is_dynamic_array(left.resultdef) then
  146. hlcg.a_op_const_reg(current_asmdata.CurrAsmList,OP_ADD,resultdef,1,hregister);
  147. hlcg.a_load_reg_ref(current_asmdata.CurrAsmList,resultdef,resultdef,hregister,tempref);
  148. hlcg.a_jmp_always(current_asmdata.CurrAsmList,lengthlab);
  149. hlcg.a_label(current_asmdata.CurrAsmList,nillab);
  150. hlcg.a_load_const_ref(current_asmdata.CurrAsmList,resultdef,0,tempref);
  151. hlcg.a_label(current_asmdata.CurrAsmList,lengthlab);
  152. hregister:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  153. hlcg.a_load_ref_reg(current_asmdata.CurrAsmList,resultdef,resultdef,tempref,hregister);
  154. tg.ungettemp(current_asmdata.CurrAsmList,tempref);
  155. location_reset(location,LOC_REGISTER,def_cgsize(resultdef));
  156. location.register:=hregister;
  157. end;
  158. end;
  159. procedure tllvminlinenode.second_sqr_real;
  160. begin
  161. secondpass(left);
  162. location.loc:=expectloc;
  163. if expectloc=LOC_MMREGISTER then
  164. begin
  165. hlcg.location_force_mmregscalar(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
  166. location.register:=hlcg.getmmregister(current_asmdata.CurrAsmList,resultdef);
  167. end
  168. else
  169. begin
  170. hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
  171. location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
  172. end;
  173. current_asmdata.CurrAsmList.concat(
  174. taillvm.op_reg_size_reg_reg(la_fmul,
  175. location.register,resultdef,
  176. left.location.register,left.location.register
  177. )
  178. );
  179. end;
  180. begin
  181. cinlinenode:=tllvminlinenode;
  182. end.