github.com/tcnksm/go@v0.0.0-20141208075154-439b32936367/src/cmd/gc/cplx.c (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 #include <u.h> 6 #include <libc.h> 7 #include "gg.h" 8 9 static void subnode(Node *nr, Node *ni, Node *nc); 10 static void minus(Node *nl, Node *res); 11 void complexminus(Node*, Node*); 12 void complexadd(int op, Node*, Node*, Node*); 13 void complexmul(Node*, Node*, Node*); 14 15 #define CASE(a,b) (((a)<<16)|((b)<<0)) 16 17 static int 18 overlap(Node *f, Node *t) 19 { 20 // check whether f and t could be overlapping stack references. 21 // not exact, because it's hard to check for the stack register 22 // in portable code. close enough: worst case we will allocate 23 // an extra temporary and the registerizer will clean it up. 24 return f->op == OINDREG && 25 t->op == OINDREG && 26 f->xoffset+f->type->width >= t->xoffset && 27 t->xoffset+t->type->width >= f->xoffset; 28 } 29 30 /* 31 * generate: 32 * res = n; 33 * simplifies and calls gmove. 34 */ 35 void 36 complexmove(Node *f, Node *t) 37 { 38 int ft, tt; 39 Node n1, n2, n3, n4, tmp; 40 41 if(debug['g']) { 42 dump("\ncomplexmove-f", f); 43 dump("complexmove-t", t); 44 } 45 46 if(!t->addable) 47 fatal("complexmove: to not addable"); 48 49 ft = simsimtype(f->type); 50 tt = simsimtype(t->type); 51 switch(CASE(ft,tt)) { 52 53 default: 54 fatal("complexmove: unknown conversion: %T -> %T\n", 55 f->type, t->type); 56 57 case CASE(TCOMPLEX64,TCOMPLEX64): 58 case CASE(TCOMPLEX64,TCOMPLEX128): 59 case CASE(TCOMPLEX128,TCOMPLEX64): 60 case CASE(TCOMPLEX128,TCOMPLEX128): 61 // complex to complex move/convert. 62 // make f addable. 63 // also use temporary if possible stack overlap. 64 if(!f->addable || overlap(f, t)) { 65 tempname(&tmp, f->type); 66 complexmove(f, &tmp); 67 f = &tmp; 68 } 69 70 subnode(&n1, &n2, f); 71 subnode(&n3, &n4, t); 72 73 cgen(&n1, &n3); 74 cgen(&n2, &n4); 75 break; 76 } 77 } 78 79 int 80 complexop(Node *n, Node *res) 81 { 82 if(n != N && n->type != T) 83 if(iscomplex[n->type->etype]) { 84 goto maybe; 85 } 86 if(res != N && res->type != T) 87 if(iscomplex[res->type->etype]) { 88 goto maybe; 89 } 90 91 if(n->op == OREAL || n->op == OIMAG) 92 goto yes; 93 94 goto no; 95 96 maybe: 97 switch(n->op) { 98 case OCONV: // implemented ops 99 case OADD: 100 case OSUB: 101 case OMUL: 102 case OMINUS: 103 case OCOMPLEX: 104 case OREAL: 105 case OIMAG: 106 goto yes; 107 108 case ODOT: 109 case ODOTPTR: 110 case OINDEX: 111 case OIND: 112 case ONAME: 113 goto yes; 114 } 115 116 no: 117 //dump("\ncomplex-no", n); 118 return 0; 119 yes: 120 //dump("\ncomplex-yes", n); 121 return 1; 122 } 123 124 void 125 complexgen(Node *n, Node *res) 126 { 127 Node *nl, *nr; 128 Node tnl, tnr; 129 Node n1, n2, tmp; 130 int tl, tr; 131 132 if(debug['g']) { 133 dump("\ncomplexgen-n", n); 134 dump("complexgen-res", res); 135 } 136 137 while(n->op == OCONVNOP) 138 n = n->left; 139 140 // pick off float/complex opcodes 141 switch(n->op) { 142 case OCOMPLEX: 143 if(res->addable) { 144 subnode(&n1, &n2, res); 145 tempname(&tmp, n1.type); 146 cgen(n->left, &tmp); 147 cgen(n->right, &n2); 148 cgen(&tmp, &n1); 149 return; 150 } 151 break; 152 153 case OREAL: 154 case OIMAG: 155 nl = n->left; 156 if(!nl->addable) { 157 tempname(&tmp, nl->type); 158 complexgen(nl, &tmp); 159 nl = &tmp; 160 } 161 subnode(&n1, &n2, nl); 162 if(n->op == OREAL) { 163 cgen(&n1, res); 164 return; 165 } 166 cgen(&n2, res); 167 return; 168 } 169 170 // perform conversion from n to res 171 tl = simsimtype(res->type); 172 tl = cplxsubtype(tl); 173 tr = simsimtype(n->type); 174 tr = cplxsubtype(tr); 175 if(tl != tr) { 176 if(!n->addable) { 177 tempname(&n1, n->type); 178 complexmove(n, &n1); 179 n = &n1; 180 } 181 complexmove(n, res); 182 return; 183 } 184 185 if(!res->addable) { 186 igen(res, &n1, N); 187 cgen(n, &n1); 188 regfree(&n1); 189 return; 190 } 191 if(n->addable) { 192 complexmove(n, res); 193 return; 194 } 195 196 switch(n->op) { 197 default: 198 dump("complexgen: unknown op", n); 199 fatal("complexgen: unknown op %O", n->op); 200 201 case ODOT: 202 case ODOTPTR: 203 case OINDEX: 204 case OIND: 205 case ONAME: // PHEAP or PPARAMREF var 206 case OCALLFUNC: 207 case OCALLMETH: 208 case OCALLINTER: 209 igen(n, &n1, res); 210 complexmove(&n1, res); 211 regfree(&n1); 212 return; 213 214 case OCONV: 215 case OADD: 216 case OSUB: 217 case OMUL: 218 case OMINUS: 219 case OCOMPLEX: 220 case OREAL: 221 case OIMAG: 222 break; 223 } 224 225 nl = n->left; 226 if(nl == N) 227 return; 228 nr = n->right; 229 230 // make both sides addable in ullman order 231 if(nr != N) { 232 if(nl->ullman > nr->ullman && !nl->addable) { 233 tempname(&tnl, nl->type); 234 cgen(nl, &tnl); 235 nl = &tnl; 236 } 237 if(!nr->addable) { 238 tempname(&tnr, nr->type); 239 cgen(nr, &tnr); 240 nr = &tnr; 241 } 242 } 243 if(!nl->addable) { 244 tempname(&tnl, nl->type); 245 cgen(nl, &tnl); 246 nl = &tnl; 247 } 248 249 switch(n->op) { 250 default: 251 fatal("complexgen: unknown op %O", n->op); 252 break; 253 254 case OCONV: 255 complexmove(nl, res); 256 break; 257 258 case OMINUS: 259 complexminus(nl, res); 260 break; 261 262 case OADD: 263 case OSUB: 264 complexadd(n->op, nl, nr, res); 265 break; 266 267 case OMUL: 268 complexmul(nl, nr, res); 269 break; 270 } 271 } 272 273 void 274 complexbool(int op, Node *nl, Node *nr, int true, int likely, Prog *to) 275 { 276 Node tnl, tnr; 277 Node n1, n2, n3, n4; 278 Node na, nb, nc; 279 280 // make both sides addable in ullman order 281 if(nr != N) { 282 if(nl->ullman > nr->ullman && !nl->addable) { 283 tempname(&tnl, nl->type); 284 cgen(nl, &tnl); 285 nl = &tnl; 286 } 287 if(!nr->addable) { 288 tempname(&tnr, nr->type); 289 cgen(nr, &tnr); 290 nr = &tnr; 291 } 292 } 293 if(!nl->addable) { 294 tempname(&tnl, nl->type); 295 cgen(nl, &tnl); 296 nl = &tnl; 297 } 298 299 // build tree 300 // real(l) == real(r) && imag(l) == imag(r) 301 302 subnode(&n1, &n2, nl); 303 subnode(&n3, &n4, nr); 304 305 memset(&na, 0, sizeof(na)); 306 na.op = OANDAND; 307 na.left = &nb; 308 na.right = &nc; 309 na.type = types[TBOOL]; 310 311 memset(&nb, 0, sizeof(na)); 312 nb.op = OEQ; 313 nb.left = &n1; 314 nb.right = &n3; 315 nb.type = types[TBOOL]; 316 317 memset(&nc, 0, sizeof(na)); 318 nc.op = OEQ; 319 nc.left = &n2; 320 nc.right = &n4; 321 nc.type = types[TBOOL]; 322 323 if(op == ONE) 324 true = !true; 325 326 bgen(&na, true, likely, to); 327 } 328 329 void 330 nodfconst(Node *n, Type *t, Mpflt* fval) 331 { 332 memset(n, 0, sizeof(*n)); 333 n->op = OLITERAL; 334 n->addable = 1; 335 ullmancalc(n); 336 n->val.u.fval = fval; 337 n->val.ctype = CTFLT; 338 n->type = t; 339 340 if(!isfloat[t->etype]) 341 fatal("nodfconst: bad type %T", t); 342 } 343 344 // break addable nc-complex into nr-real and ni-imaginary 345 static void 346 subnode(Node *nr, Node *ni, Node *nc) 347 { 348 int tc; 349 Type *t; 350 351 if(!nc->addable) 352 fatal("subnode not addable"); 353 354 tc = simsimtype(nc->type); 355 tc = cplxsubtype(tc); 356 t = types[tc]; 357 358 if(nc->op == OLITERAL) { 359 nodfconst(nr, t, &nc->val.u.cval->real); 360 nodfconst(ni, t, &nc->val.u.cval->imag); 361 return; 362 } 363 364 *nr = *nc; 365 nr->type = t; 366 367 *ni = *nc; 368 ni->type = t; 369 ni->xoffset += t->width; 370 } 371 372 // generate code res = -nl 373 static void 374 minus(Node *nl, Node *res) 375 { 376 Node ra; 377 378 memset(&ra, 0, sizeof(ra)); 379 ra.op = OMINUS; 380 ra.left = nl; 381 ra.type = nl->type; 382 cgen(&ra, res); 383 } 384 385 // build and execute tree 386 // real(res) = -real(nl) 387 // imag(res) = -imag(nl) 388 void 389 complexminus(Node *nl, Node *res) 390 { 391 Node n1, n2, n5, n6; 392 393 subnode(&n1, &n2, nl); 394 subnode(&n5, &n6, res); 395 396 minus(&n1, &n5); 397 minus(&n2, &n6); 398 } 399 400 401 // build and execute tree 402 // real(res) = real(nl) op real(nr) 403 // imag(res) = imag(nl) op imag(nr) 404 void 405 complexadd(int op, Node *nl, Node *nr, Node *res) 406 { 407 Node n1, n2, n3, n4, n5, n6; 408 Node ra; 409 410 subnode(&n1, &n2, nl); 411 subnode(&n3, &n4, nr); 412 subnode(&n5, &n6, res); 413 414 memset(&ra, 0, sizeof(ra)); 415 ra.op = op; 416 ra.left = &n1; 417 ra.right = &n3; 418 ra.type = n1.type; 419 cgen(&ra, &n5); 420 421 memset(&ra, 0, sizeof(ra)); 422 ra.op = op; 423 ra.left = &n2; 424 ra.right = &n4; 425 ra.type = n2.type; 426 cgen(&ra, &n6); 427 } 428 429 // build and execute tree 430 // tmp = real(nl)*real(nr) - imag(nl)*imag(nr) 431 // imag(res) = real(nl)*imag(nr) + imag(nl)*real(nr) 432 // real(res) = tmp 433 void 434 complexmul(Node *nl, Node *nr, Node *res) 435 { 436 Node n1, n2, n3, n4, n5, n6; 437 Node rm1, rm2, ra, tmp; 438 439 subnode(&n1, &n2, nl); 440 subnode(&n3, &n4, nr); 441 subnode(&n5, &n6, res); 442 tempname(&tmp, n5.type); 443 444 // real part -> tmp 445 memset(&rm1, 0, sizeof(ra)); 446 rm1.op = OMUL; 447 rm1.left = &n1; 448 rm1.right = &n3; 449 rm1.type = n1.type; 450 451 memset(&rm2, 0, sizeof(ra)); 452 rm2.op = OMUL; 453 rm2.left = &n2; 454 rm2.right = &n4; 455 rm2.type = n2.type; 456 457 memset(&ra, 0, sizeof(ra)); 458 ra.op = OSUB; 459 ra.left = &rm1; 460 ra.right = &rm2; 461 ra.type = rm1.type; 462 cgen(&ra, &tmp); 463 464 // imag part 465 memset(&rm1, 0, sizeof(ra)); 466 rm1.op = OMUL; 467 rm1.left = &n1; 468 rm1.right = &n4; 469 rm1.type = n1.type; 470 471 memset(&rm2, 0, sizeof(ra)); 472 rm2.op = OMUL; 473 rm2.left = &n2; 474 rm2.right = &n3; 475 rm2.type = n2.type; 476 477 memset(&ra, 0, sizeof(ra)); 478 ra.op = OADD; 479 ra.left = &rm1; 480 ra.right = &rm2; 481 ra.type = rm1.type; 482 cgen(&ra, &n6); 483 484 // tmp ->real part 485 cgen(&tmp, &n5); 486 }