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