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  }