nllvmadd.pas 7.2 KB

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