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