1 { 2 Copyright (c) 2013 by Jonas Maebe 3 4 Generate LLVM bytecode for add nodes 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 20 **************************************************************************** 21 } 22 unit nllvmadd; 23 24 {$i fpcdefs.inc} 25 26 interface 27 28 uses 29 node, 30 ncgadd; 31 32 type 33 tllvmaddnode = class(tcgaddnode) 34 public pass_1null35 function pass_1: tnode; override; 36 procedure force_reg_left_right(allow_swap, allow_constant: boolean); override; 37 protected 38 procedure second_cmpsmallset; override; 39 procedure second_cmpordinal; override; 40 procedure second_add64bit; override; 41 procedure second_cmp64bit; override; 42 procedure second_addfloat; override; 43 procedure second_cmpfloat; override; 44 end; 45 46 47 implementation 48 49 uses 50 verbose,globtype, 51 aasmdata, 52 symconst,symtype,symdef,defutil, 53 llvmbase,aasmllvm, 54 cgbase,cgutils, 55 hlcgobj, 56 nadd 57 ; 58 59 { tllvmaddnode } 60 tllvmaddnode.pass_1null61 function tllvmaddnode.pass_1: tnode; 62 begin 63 result:=inherited pass_1; 64 { there are no flags in LLVM } 65 if expectloc=LOC_FLAGS then 66 expectloc:=LOC_REGISTER; 67 end; 68 69 70 procedure tllvmaddnode.force_reg_left_right(allow_swap, allow_constant: boolean); 71 begin 72 { comparison with pointer -> no immediate, as icmp can't handle pointer 73 immediates (except for nil as "null", but we don't generate that) } 74 if (nodetype in [equaln,unequaln,gtn,gten,ltn,lten]) and 75 ((left.nodetype in [pointerconstn,niln]) or 76 (right.nodetype in [pointerconstn,niln])) then 77 allow_constant:=false; 78 inherited; 79 { pointer - pointer = integer -> make all defs pointer since we can't 80 subtract pointers } 81 if (nodetype=subn) and 82 (left.resultdef.typ=pointerdef) and 83 (right.resultdef.typ=pointerdef) then 84 begin 85 hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,true); 86 hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,resultdef,true); 87 end 88 { pointer +/- integer -> make defs the same since a_op_* only gets a 89 single type as argument } 90 else if (nodetype in [addn,subn]) and 91 ((left.resultdef.typ=pointerdef)<>(right.resultdef.typ=pointerdef)) then 92 begin 93 { the result is a pointerdef -> typecast both arguments to pointer; 94 a_op_*_reg will convert them back to integer as needed } 95 if left.resultdef.typ<>pointerdef then 96 hlcg.location_force_reg(current_asmdata.CurrAsmList,left.location,left.resultdef,resultdef,true); 97 if right.resultdef.typ<>pointerdef then 98 hlcg.location_force_reg(current_asmdata.CurrAsmList,right.location,right.resultdef,resultdef,true); 99 end; 100 end; 101 102 103 procedure tllvmaddnode.second_cmpsmallset; 104 var 105 tmpreg, 106 tmpreg2: tregister; 107 cmpop : topcmp; 108 begin 109 pass_left_right; 110 111 location_reset(location,LOC_REGISTER,OS_8); 112 location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,llvmbool1type); 113 114 force_reg_left_right(false,false); 115 116 case nodetype of 117 equaln, 118 unequaln: 119 begin 120 if nodetype=equaln then 121 cmpop:=OC_EQ 122 else 123 cmpop:=OC_NE; 124 current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp, 125 location.register,cmpop,left.resultdef,left.location.register,right.location.register)); 126 end; 127 lten, 128 gten: 129 begin 130 if (not(nf_swapped in flags) and 131 (nodetype = lten)) or 132 ((nf_swapped in flags) and 133 (nodetype = gten)) then 134 swapleftright; 135 { set1<=set2 <-> set2 and not(set1) = 0 } 136 tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,left.resultdef); 137 hlcg.a_op_reg_reg(current_asmdata.CurrAsmList,OP_NOT,left.resultdef,left.location.register,tmpreg); 138 tmpreg2:=hlcg.getintregister(current_asmdata.CurrAsmList,left.resultdef); 139 hlcg.a_op_reg_reg_reg(current_asmdata.CurrAsmList,OP_AND,left.resultdef,right.location.register,tmpreg,tmpreg2); 140 current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp, 141 location.register,OC_EQ,left.resultdef,tmpreg2,0)); 142 end; 143 else 144 internalerror(2012042701); 145 end; 146 tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef); 147 hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,llvmbool1type,resultdef,location.register,tmpreg); 148 location.register:=tmpreg; 149 end; 150 151 152 procedure tllvmaddnode.second_cmpordinal; 153 var 154 tmpreg: tregister; 155 cmpop: topcmp; 156 unsigned : boolean; 157 begin 158 pass_left_right; 159 force_reg_left_right(true,true); 160 161 unsigned:=not(is_signed(left.resultdef)) or 162 not(is_signed(right.resultdef)); 163 164 case nodetype of 165 ltn: 166 if unsigned then 167 cmpop:=OC_B 168 else 169 cmpop:=OC_LT; 170 lten: 171 if unsigned then 172 cmpop:=OC_BE 173 else 174 cmpop:=OC_LTE; 175 gtn: 176 if unsigned then 177 cmpop:=OC_A 178 else 179 cmpop:=OC_GT; 180 gten: 181 if unsigned then 182 cmpop:=OC_AE 183 else 184 cmpop:=OC_GTE; 185 equaln: 186 cmpop:=OC_EQ; 187 unequaln: 188 cmpop:=OC_NE; 189 else 190 internalerror(2015031505); 191 end; 192 if nf_swapped in flags then 193 cmpop:=swap_opcmp(cmpop); 194 195 location_reset(location,LOC_REGISTER,OS_8); 196 location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,llvmbool1type); 197 198 if right.location.loc=LOC_CONSTANT then 199 current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_const(la_icmp, 200 location.register,cmpop,left.resultdef,left.location.register,right.location.value64)) 201 else 202 current_asmdata.CurrAsmList.concat(taillvm.op_reg_cond_size_reg_reg(la_icmp, 203 location.register,cmpop,left.resultdef,left.location.register,right.location.register)); 204 205 tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef); 206 hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,llvmbool1type,resultdef,location.register,tmpreg); 207 location.register:=tmpreg; 208 end; 209 210 211 procedure tllvmaddnode.second_add64bit; 212 begin 213 second_addordinal; 214 end; 215 216 217 procedure tllvmaddnode.second_cmp64bit; 218 begin 219 second_cmpordinal; 220 end; 221 222 223 procedure tllvmaddnode.second_addfloat; 224 var 225 tmpreg: tregister; 226 op : tllvmop; 227 llvmfpcmp : tllvmfpcmp; 228 size : tdef; 229 cmpop, 230 singleprec : boolean; 231 begin 232 pass_left_right; 233 234 cmpop:=false; 235 singleprec:=tfloatdef(left.resultdef).floattype=s32real; 236 { avoid uninitialised warning } 237 llvmfpcmp:=lfc_invalid; 238 case nodetype of 239 addn : 240 op:=la_fadd; 241 muln : 242 op:=la_fmul; 243 subn : 244 op:=la_fsub; 245 slashn : 246 op:=la_fdiv; 247 ltn,lten,gtn,gten, 248 equaln,unequaln : 249 begin 250 op:=la_fcmp; 251 cmpop:=true; 252 case nodetype of 253 ltn: 254 llvmfpcmp:=lfc_olt; 255 lten: 256 llvmfpcmp:=lfc_ole; 257 gtn: 258 llvmfpcmp:=lfc_ogt; 259 gten: 260 llvmfpcmp:=lfc_oge; 261 equaln: 262 llvmfpcmp:=lfc_oeq; 263 unequaln: 264 llvmfpcmp:=lfc_one; 265 else 266 internalerror(2015031506); 267 end; 268 end; 269 else 270 internalerror(2013102401); 271 end; 272 273 { get the operands in the correct order; there are no special cases here, 274 everything is register-based } 275 if nf_swapped in flags then 276 swapleftright; 277 278 { put both operands in a register } 279 hlcg.location_force_fpureg(current_asmdata.CurrAsmList,right.location,right.resultdef,true); 280 hlcg.location_force_fpureg(current_asmdata.CurrAsmList,left.location,left.resultdef,true); 281 282 { initialize the result location } 283 if not cmpop then 284 begin 285 location_reset(location,LOC_FPUREGISTER,def_cgsize(resultdef)); 286 location.register:=hlcg.getfpuregister(current_asmdata.CurrAsmList,resultdef); 287 end 288 else 289 begin 290 location_reset(location,LOC_REGISTER,OS_8); 291 location.register:=hlcg.getintregister(current_asmdata.CurrAsmList,llvmbool1type); 292 end; 293 294 { see comment in thlcgllvm.a_loadfpu_ref_reg } 295 if tfloatdef(left.resultdef).floattype in [s64comp,s64currency] then 296 size:=sc80floattype 297 else 298 size:=left.resultdef; 299 300 { emit the actual operation } 301 if not cmpop then 302 begin 303 current_asmdata.CurrAsmList.concat(taillvm.op_reg_size_reg_reg(op,location.register,size, 304 left.location.register,right.location.register)) 305 end 306 else 307 begin 308 current_asmdata.CurrAsmList.concat(taillvm.op_reg_fpcond_size_reg_reg(op, 309 location.register,llvmfpcmp,size,left.location.register,right.location.register)); 310 tmpreg:=hlcg.getintregister(current_asmdata.CurrAsmList,resultdef); 311 hlcg.a_load_reg_reg(current_asmdata.CurrAsmList,llvmbool1type,resultdef,location.register,tmpreg); 312 location.register:=tmpreg; 313 end; 314 end; 315 316 317 procedure tllvmaddnode.second_cmpfloat; 318 begin 319 second_addfloat; 320 end; 321 322 323 begin 324 caddnode:=tllvmaddnode; 325 end. 326 327