nllvmadd.pas 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. {
  2. Copyright (c) 2013 by Jonas Maebe
  3. Generate LLVM bytecode for add 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 nllvmadd;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. node,
  22. ncgadd;
  23. type
  24. tllvmaddnode = class(tcgaddnode)
  25. public
  26. function pass_1: tnode; override;
  27. protected
  28. procedure second_cmpsmallset; override;
  29. procedure second_cmpordinal; override;
  30. procedure second_add64bit; override;
  31. procedure second_cmp64bit; override;
  32. procedure second_addfloat; override;
  33. procedure second_cmpfloat; override;
  34. end;
  35. implementation
  36. uses
  37. verbose,globtype,
  38. aasmdata,
  39. symtype,symdef,defutil,
  40. llvmbase,aasmllvm,
  41. cgbase,cgutils,
  42. hlcgobj,
  43. nadd
  44. ;
  45. { tllvmaddnode }
  46. function tllvmaddnode.pass_1: tnode;
  47. begin
  48. result:=inherited pass_1;
  49. { there are no flags in LLVM }
  50. if expectloc=LOC_FLAGS then
  51. expectloc:=LOC_REGISTER;
  52. end;
  53. procedure tllvmaddnode.second_cmpsmallset;
  54. var
  55. tmpreg,
  56. tmpreg2: tregister;
  57. cmpop : topcmp;
  58. begin
  59. pass_left_right;
  60. location_reset(location,LOC_REGISTER,OS_8);
  61. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,pasbool8type);
  62. force_reg_left_right(false,false);
  63. case nodetype of
  64. equaln,
  65. unequaln:
  66. begin
  67. if nodetype=equaln then
  68. cmpop:=OC_EQ
  69. else
  70. cmpop:=OC_NE;
  71. current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp,
  72. location.register,cmpop,left.resultdef,left.location.register,right.location.register));
  73. end;
  74. lten,
  75. gten:
  76. begin
  77. if (not(nf_swapped in flags) and
  78. (nodetype = lten)) or
  79. ((nf_swapped in flags) and
  80. (nodetype = gten)) then
  81. swapleftright;
  82. { set1<=set2 <-> set2 and not(set1) = 0 }
  83. tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,left.resultdef);
  84. hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,left.resultdef,left.location.register,tmpreg);
  85. tmpreg2:=hlcg.getintregister(current_asmdata.CurrAsmList,left.resultdef);
  86. hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_AND,left.resultdef,right.location.register,tmpreg,tmpreg2);
  87. current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,
  88. location.register,OC_EQ,left.resultdef,tmpreg2,0));
  89. end;
  90. else
  91. internalerror(2012042701);
  92. end;
  93. end;
  94. procedure tllvmaddnode.second_cmpordinal;
  95. var
  96. cmpop: topcmp;
  97. unsigned : boolean;
  98. begin
  99. pass_left_right;
  100. force_reg_left_right(true,true);
  101. unsigned:=not(is_signed(left.resultdef)) or
  102. not(is_signed(right.resultdef));
  103. case nodetype of
  104. ltn:
  105. if unsigned then
  106. cmpop:=OC_B
  107. else
  108. cmpop:=OC_LT;
  109. lten:
  110. if unsigned then
  111. cmpop:=OC_BE
  112. else
  113. cmpop:=OC_LTE;
  114. gtn:
  115. if unsigned then
  116. cmpop:=OC_A
  117. else
  118. cmpop:=OC_GT;
  119. gten:
  120. if unsigned then
  121. cmpop:=OC_AE
  122. else
  123. cmpop:=OC_GTE;
  124. equaln:
  125. cmpop:=OC_EQ;
  126. unequaln:
  127. cmpop:=OC_NE;
  128. end;
  129. if nf_swapped in flags then
  130. cmpop:=swap_opcmp(cmpop);
  131. location_reset(location,LOC_REGISTER,OS_8);
  132. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  133. if right.location.loc=LOC_CONSTANT then
  134. current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp,
  135. location.register,cmpop,left.resultdef,left.location.register,right.location.value64))
  136. else
  137. current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp,
  138. location.register,cmpop,left.resultdef,left.location.register,right.location.register));
  139. end;
  140. procedure tllvmaddnode.second_add64bit;
  141. begin
  142. second_addordinal;
  143. end;
  144. procedure tllvmaddnode.second_cmp64bit;
  145. begin
  146. second_cmpordinal;
  147. end;
  148. procedure tllvmaddnode.second_addfloat;
  149. var
  150. op : tllvmop;
  151. llvmfpcmp : tllvmfpcmp;
  152. size : tdef;
  153. cmpop,
  154. singleprec : boolean;
  155. begin
  156. pass_left_right;
  157. cmpop:=false;
  158. singleprec:=tfloatdef(left.resultdef).floattype=s32real;
  159. case nodetype of
  160. addn :
  161. op:=la_fadd;
  162. muln :
  163. op:=la_fmul;
  164. subn :
  165. op:=la_fsub;
  166. slashn :
  167. op:=la_fdiv;
  168. ltn,lten,gtn,gten,
  169. equaln,unequaln :
  170. begin
  171. op:=la_fcmp;
  172. cmpop:=true;
  173. case nodetype of
  174. ltn:
  175. llvmfpcmp:=lfc_olt;
  176. lten:
  177. llvmfpcmp:=lfc_ole;
  178. gtn:
  179. llvmfpcmp:=lfc_ogt;
  180. gten:
  181. llvmfpcmp:=lfc_oge;
  182. equaln:
  183. llvmfpcmp:=lfc_oeq;
  184. unequaln:
  185. llvmfpcmp:=lfc_one;
  186. end;
  187. end;
  188. else
  189. internalerror(2013102401);
  190. end;
  191. { get the operands in the correct order; there are no special cases here,
  192. everything is register-based }
  193. if nf_swapped in flags then
  194. swapleftright;
  195. { put both operands in a register }
  196. hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true);
  197. hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true);
  198. { initialize the result location }
  199. if not cmpop then
  200. begin
  201. location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef));
  202. location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef);
  203. end
  204. else
  205. begin
  206. location_reset(location,LOC_REGISTER,OS_8);
  207. location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef);
  208. end;
  209. { see comment in thlcgllvm.a_loadfpu_ref_reg }
  210. if tfloatdef(left.resultdef).floattype in [s64comp,s64currency] then
  211. size:=sc80floattype
  212. else
  213. size:=left.resultdef;
  214. { emit the actual operation }
  215. if not cmpop then
  216. begin
  217. current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_reg_reg(op,location.register,size,
  218. left.location.register,right.location.register))
  219. end
  220. else
  221. begin
  222. current_asmdata.CurrAsmList.concat(taillvm.op_reg_fpcond_size_reg_reg(op,
  223. location.register,llvmfpcmp,size,left.location.register,right.location.register))
  224. end;
  225. end;
  226. procedure tllvmaddnode.second_cmpfloat;
  227. begin
  228. second_addfloat;
  229. end;
  230. begin
  231. caddnode:=tllvmaddnode;
  232. end.