cmd/compile/internal: named types for Etype and Op in struct Node

Type Op is enfored now.
Type EType will need further CLs.
Added TODOs where Node.EType is used as a union type.
The TODOs have the format `TODO(marvin): Fix Node.EType union type.`.

Furthermore:
-The flag of Econv function in fmt.go is removed, since unused.
-Some cleaning along the way, e.g. declare vars first when getting initialized.

Passes go build -toolexec 'toolstash -cmp' -a std.

Fixes #11846

Change-Id: I908b955d5a78a195604970983fb9194bd9e9260b
Reviewed-on: https://go-review.googlesource.com/14956
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Marvin Stenger <marvin.stenger94@gmail.com>
diff --git a/src/cmd/compile/internal/gc/align.go b/src/cmd/compile/internal/gc/align.go
index 5e14047..812a8cb 100644
--- a/src/cmd/compile/internal/gc/align.go
+++ b/src/cmd/compile/internal/gc/align.go
@@ -149,7 +149,7 @@
 	t.Width = -2
 	t.Align = 0
 
-	et := int32(t.Etype)
+	et := t.Etype
 	switch et {
 	case TFUNC, TCHAN, TMAP, TSTRING:
 		break
@@ -157,7 +157,7 @@
 	// simtype == 0 during bootstrap
 	default:
 		if Simtype[t.Etype] != 0 {
-			et = int32(Simtype[t.Etype])
+			et = Simtype[t.Etype]
 		}
 	}
 
@@ -416,8 +416,8 @@
 		Fatalf("typeinit before betypeinit")
 	}
 
-	for i := 0; i < NTYPE; i++ {
-		Simtype[i] = uint8(i)
+	for et := EType(0); et < NTYPE; et++ {
+		Simtype[et] = et
 	}
 
 	Types[TPTR32] = typ(TPTR32)
@@ -439,8 +439,8 @@
 		Tptr = TPTR64
 	}
 
-	for i := TINT8; i <= TUINT64; i++ {
-		Isint[i] = true
+	for et := TINT8; et <= TUINT64; et++ {
+		Isint[et] = true
 	}
 	Isint[TINT] = true
 	Isint[TUINT] = true
@@ -464,36 +464,36 @@
 	Issigned[TINT64] = true
 
 	// initialize okfor
-	for i := 0; i < NTYPE; i++ {
-		if Isint[i] || i == TIDEAL {
-			okforeq[i] = true
-			okforcmp[i] = true
-			okforarith[i] = true
-			okforadd[i] = true
-			okforand[i] = true
-			okforconst[i] = true
-			issimple[i] = true
-			Minintval[i] = new(Mpint)
-			Maxintval[i] = new(Mpint)
+	for et := EType(0); et < NTYPE; et++ {
+		if Isint[et] || et == TIDEAL {
+			okforeq[et] = true
+			okforcmp[et] = true
+			okforarith[et] = true
+			okforadd[et] = true
+			okforand[et] = true
+			okforconst[et] = true
+			issimple[et] = true
+			Minintval[et] = new(Mpint)
+			Maxintval[et] = new(Mpint)
 		}
 
-		if Isfloat[i] {
-			okforeq[i] = true
-			okforcmp[i] = true
-			okforadd[i] = true
-			okforarith[i] = true
-			okforconst[i] = true
-			issimple[i] = true
-			minfltval[i] = newMpflt()
-			maxfltval[i] = newMpflt()
+		if Isfloat[et] {
+			okforeq[et] = true
+			okforcmp[et] = true
+			okforadd[et] = true
+			okforarith[et] = true
+			okforconst[et] = true
+			issimple[et] = true
+			minfltval[et] = newMpflt()
+			maxfltval[et] = newMpflt()
 		}
 
-		if Iscomplex[i] {
-			okforeq[i] = true
-			okforadd[i] = true
-			okforarith[i] = true
-			okforconst[i] = true
-			issimple[i] = true
+		if Iscomplex[et] {
+			okforeq[et] = true
+			okforadd[et] = true
+			okforarith[et] = true
+			okforconst[et] = true
+			issimple[et] = true
 		}
 	}
 
@@ -612,30 +612,26 @@
 	Types[TINTER] = typ(TINTER)
 
 	// simple aliases
-	Simtype[TMAP] = uint8(Tptr)
+	Simtype[TMAP] = Tptr
 
-	Simtype[TCHAN] = uint8(Tptr)
-	Simtype[TFUNC] = uint8(Tptr)
-	Simtype[TUNSAFEPTR] = uint8(Tptr)
+	Simtype[TCHAN] = Tptr
+	Simtype[TFUNC] = Tptr
+	Simtype[TUNSAFEPTR] = Tptr
 
 	// pick up the backend thearch.typedefs
-	var s1 *Sym
-	var etype int
-	var sameas int
-	var s *Sym
 	for i = range Thearch.Typedefs {
-		s = Lookup(Thearch.Typedefs[i].Name)
-		s1 = Pkglookup(Thearch.Typedefs[i].Name, builtinpkg)
+		s := Lookup(Thearch.Typedefs[i].Name)
+		s1 := Pkglookup(Thearch.Typedefs[i].Name, builtinpkg)
 
-		etype = Thearch.Typedefs[i].Etype
-		if etype < 0 || etype >= len(Types) {
+		etype := Thearch.Typedefs[i].Etype
+		if int(etype) >= len(Types) {
 			Fatalf("typeinit: %s bad etype", s.Name)
 		}
-		sameas = Thearch.Typedefs[i].Sameas
-		if sameas < 0 || sameas >= len(Types) {
+		sameas := Thearch.Typedefs[i].Sameas
+		if int(sameas) >= len(Types) {
 			Fatalf("typeinit: %s bad sameas", s.Name)
 		}
-		Simtype[etype] = uint8(sameas)
+		Simtype[etype] = sameas
 		minfltval[etype] = minfltval[sameas]
 		maxfltval[etype] = maxfltval[sameas]
 		Minintval[etype] = Minintval[sameas]
diff --git a/src/cmd/compile/internal/gc/bimport.go b/src/cmd/compile/internal/gc/bimport.go
index 08e5dd7..731f31b 100644
--- a/src/cmd/compile/internal/gc/bimport.go
+++ b/src/cmd/compile/internal/gc/bimport.go
@@ -182,7 +182,7 @@
 	return importpkg.Lookup(name)
 }
 
-func (p *importer) newtyp(etype int) *Type {
+func (p *importer) newtyp(etype EType) *Type {
 	t := typ(etype)
 	p.typList = append(p.typList, t)
 	return t
diff --git a/src/cmd/compile/internal/gc/cgen.go b/src/cmd/compile/internal/gc/cgen.go
index 9504a0f..8cbdd18 100644
--- a/src/cmd/compile/internal/gc/cgen.go
+++ b/src/cmd/compile/internal/gc/cgen.go
@@ -188,7 +188,7 @@
 	}
 
 	if wb {
-		if int(Simtype[res.Type.Etype]) != Tptr {
+		if Simtype[res.Type.Etype] != Tptr {
 			Fatalf("cgen_wb of type %v", res.Type)
 		}
 		if n.Ullman >= UINF {
@@ -395,7 +395,7 @@
 			goto sbop
 		}
 
-		a := Thearch.Optoas(int(n.Op), nl.Type)
+		a := Thearch.Optoas(n.Op, nl.Type)
 		// unary
 		var n1 Node
 		Regalloc(&n1, nl.Type, res)
@@ -432,15 +432,15 @@
 		OXOR,
 		OADD,
 		OMUL:
-		if n.Op == OMUL && Thearch.Cgen_bmul != nil && Thearch.Cgen_bmul(int(n.Op), nl, nr, res) {
+		if n.Op == OMUL && Thearch.Cgen_bmul != nil && Thearch.Cgen_bmul(n.Op, nl, nr, res) {
 			break
 		}
-		a = Thearch.Optoas(int(n.Op), nl.Type)
+		a = Thearch.Optoas(n.Op, nl.Type)
 		goto sbop
 
 		// asymmetric binary
 	case OSUB:
-		a = Thearch.Optoas(int(n.Op), nl.Type)
+		a = Thearch.Optoas(n.Op, nl.Type)
 		goto abop
 
 	case OHMUL:
@@ -654,7 +654,7 @@
 
 	case OMOD, ODIV:
 		if Isfloat[n.Type.Etype] || Thearch.Dodiv == nil {
-			a = Thearch.Optoas(int(n.Op), nl.Type)
+			a = Thearch.Optoas(n.Op, nl.Type)
 			goto abop
 		}
 
@@ -662,7 +662,7 @@
 			var n1 Node
 			Regalloc(&n1, nl.Type, res)
 			Cgen(nl, &n1)
-			cgen_div(int(n.Op), &n1, nr, res)
+			cgen_div(n.Op, &n1, nr, res)
 			Regfree(&n1)
 		} else {
 			var n2 Node
@@ -673,14 +673,14 @@
 				n2 = *nr
 			}
 
-			cgen_div(int(n.Op), nl, &n2, res)
+			cgen_div(n.Op, nl, &n2, res)
 			if n2.Op != OLITERAL {
 				Regfree(&n2)
 			}
 		}
 
 	case OLSH, ORSH, OLROT:
-		Thearch.Cgen_shift(int(n.Op), n.Bounded, nl, nr, res)
+		Thearch.Cgen_shift(n.Op, n.Bounded, nl, nr, res)
 	}
 
 	return
@@ -1902,7 +1902,7 @@
 	// n.Op is one of OEQ, ONE, OLT, OGT, OLE, OGE
 	nl := n.Left
 	nr := n.Right
-	a := int(n.Op)
+	op := n.Op
 
 	if !wantTrue {
 		if Isfloat[nr.Type.Etype] {
@@ -1925,19 +1925,19 @@
 			return
 		}
 
-		a = Brcom(a)
+		op = Brcom(op)
 	}
 	wantTrue = true
 
 	// make simplest on right
 	if nl.Op == OLITERAL || (nl.Ullman < nr.Ullman && nl.Ullman < UINF) {
-		a = Brrev(a)
+		op = Brrev(op)
 		nl, nr = nr, nl
 	}
 
 	if Isslice(nl.Type) || Isinter(nl.Type) {
 		// front end should only leave cmp to literal nil
-		if (a != OEQ && a != ONE) || nr.Op != OLITERAL {
+		if (op != OEQ && op != ONE) || nr.Op != OLITERAL {
 			if Isslice(nl.Type) {
 				Yyerror("illegal slice comparison")
 			} else {
@@ -1956,13 +1956,13 @@
 		Regalloc(&tmp, ptr.Type, &ptr)
 		Cgen(&ptr, &tmp)
 		Regfree(&ptr)
-		bgenNonZero(&tmp, res, a == OEQ != wantTrue, likely, to)
+		bgenNonZero(&tmp, res, op == OEQ != wantTrue, likely, to)
 		Regfree(&tmp)
 		return
 	}
 
 	if Iscomplex[nl.Type.Etype] {
-		complexbool(a, nl, nr, res, wantTrue, likely, to)
+		complexbool(op, nl, nr, res, wantTrue, likely, to)
 		return
 	}
 
@@ -1978,7 +1978,7 @@
 		if !nr.Addable {
 			nr = CgenTemp(nr)
 		}
-		Thearch.Cmp64(nl, nr, a, likely, to)
+		Thearch.Cmp64(nl, nr, op, likely, to)
 		return
 	}
 
@@ -2015,7 +2015,7 @@
 
 		if Smallintconst(nr) && Ctxt.Arch.Thechar != '9' {
 			Thearch.Gins(Thearch.Optoas(OCMP, nr.Type), nl, nr)
-			bins(nr.Type, res, a, likely, to)
+			bins(nr.Type, res, op, likely, to)
 			return
 		}
 
@@ -2033,9 +2033,9 @@
 	l, r := nl, nr
 
 	// On x86, only < and <= work right with NaN; reverse if needed
-	if Ctxt.Arch.Thechar == '6' && Isfloat[nl.Type.Etype] && (a == OGT || a == OGE) {
+	if Ctxt.Arch.Thechar == '6' && Isfloat[nl.Type.Etype] && (op == OGT || op == OGE) {
 		l, r = r, l
-		a = Brrev(a)
+		op = Brrev(op)
 	}
 
 	// Do the comparison.
@@ -2052,10 +2052,10 @@
 			switch n.Op {
 			case ONE:
 				Patch(Gbranch(Thearch.Optoas(OPS, nr.Type), nr.Type, likely), to)
-				Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
+				Patch(Gbranch(Thearch.Optoas(op, nr.Type), nr.Type, likely), to)
 			default:
 				p := Gbranch(Thearch.Optoas(OPS, nr.Type), nr.Type, -likely)
-				Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
+				Patch(Gbranch(Thearch.Optoas(op, nr.Type), nr.Type, likely), to)
 				Patch(p, Pc)
 			}
 			return
@@ -2101,12 +2101,12 @@
 			// On arm64 and ppc64, <= and >= mishandle NaN. Must decompose into < or > and =.
 			// TODO(josh): Convert a <= b to b > a instead?
 			case OLE, OGE:
-				if a == OLE {
-					a = OLT
+				if op == OLE {
+					op = OLT
 				} else {
-					a = OGT
+					op = OGT
 				}
-				Patch(Gbranch(Thearch.Optoas(a, nr.Type), nr.Type, likely), to)
+				Patch(Gbranch(Thearch.Optoas(op, nr.Type), nr.Type, likely), to)
 				Patch(Gbranch(Thearch.Optoas(OEQ, nr.Type), nr.Type, likely), to)
 				return
 			}
@@ -2114,26 +2114,26 @@
 	}
 
 	// Not a special case. Insert the conditional jump or value gen.
-	bins(nr.Type, res, a, likely, to)
+	bins(nr.Type, res, op, likely, to)
 }
 
 func bgenNonZero(n, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 	// TODO: Optimize on systems that can compare to zero easily.
-	a := ONE
+	var op Op = ONE
 	if !wantTrue {
-		a = OEQ
+		op = OEQ
 	}
 	var zero Node
 	Nodconst(&zero, n.Type, 0)
 	Thearch.Gins(Thearch.Optoas(OCMP, n.Type), n, &zero)
-	bins(n.Type, res, a, likely, to)
+	bins(n.Type, res, op, likely, to)
 }
 
 // bins inserts an instruction to handle the result of a compare.
 // If res is non-nil, it inserts appropriate value generation instructions.
 // If res is nil, it inserts a branch to to.
-func bins(typ *Type, res *Node, a, likely int, to *obj.Prog) {
-	a = Thearch.Optoas(a, typ)
+func bins(typ *Type, res *Node, op Op, likely int, to *obj.Prog) {
+	a := Thearch.Optoas(op, typ)
 	if res != nil {
 		// value gen
 		Thearch.Ginsboolval(a, res)
@@ -2580,7 +2580,7 @@
 // generate division according to op, one of:
 //	res = nl / nr
 //	res = nl % nr
-func cgen_div(op int, nl *Node, nr *Node, res *Node) {
+func cgen_div(op Op, nl *Node, nr *Node, res *Node) {
 	var w int
 
 	// TODO(rsc): arm64 needs to support the relevant instructions
diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go
index 7b1c020..6fe249f 100644
--- a/src/cmd/compile/internal/gc/const.go
+++ b/src/cmd/compile/internal/gc/const.go
@@ -590,13 +590,38 @@
 
 	// avoid constant conversions in switches below
 	const (
-		CTINT_  = uint32(CTINT)
-		CTRUNE_ = uint32(CTRUNE)
-		CTFLT_  = uint32(CTFLT)
-		CTCPLX_ = uint32(CTCPLX)
-		CTSTR_  = uint32(CTSTR)
-		CTBOOL_ = uint32(CTBOOL)
-		CTNIL_  = uint32(CTNIL)
+		CTINT_         = uint32(CTINT)
+		CTRUNE_        = uint32(CTRUNE)
+		CTFLT_         = uint32(CTFLT)
+		CTCPLX_        = uint32(CTCPLX)
+		CTSTR_         = uint32(CTSTR)
+		CTBOOL_        = uint32(CTBOOL)
+		CTNIL_         = uint32(CTNIL)
+		OCONV_         = uint32(OCONV) << 16
+		OARRAYBYTESTR_ = uint32(OARRAYBYTESTR) << 16
+		OPLUS_         = uint32(OPLUS) << 16
+		OMINUS_        = uint32(OMINUS) << 16
+		OCOM_          = uint32(OCOM) << 16
+		ONOT_          = uint32(ONOT) << 16
+		OLSH_          = uint32(OLSH) << 16
+		ORSH_          = uint32(ORSH) << 16
+		OADD_          = uint32(OADD) << 16
+		OSUB_          = uint32(OSUB) << 16
+		OMUL_          = uint32(OMUL) << 16
+		ODIV_          = uint32(ODIV) << 16
+		OMOD_          = uint32(OMOD) << 16
+		OOR_           = uint32(OOR) << 16
+		OAND_          = uint32(OAND) << 16
+		OANDNOT_       = uint32(OANDNOT) << 16
+		OXOR_          = uint32(OXOR) << 16
+		OEQ_           = uint32(OEQ) << 16
+		ONE_           = uint32(ONE) << 16
+		OLT_           = uint32(OLT) << 16
+		OLE_           = uint32(OLE) << 16
+		OGE_           = uint32(OGE) << 16
+		OGT_           = uint32(OGT) << 16
+		OOROR_         = uint32(OOROR) << 16
+		OANDAND_       = uint32(OANDAND) << 16
 	)
 
 	nr := n.Right
@@ -622,8 +647,8 @@
 			}
 			return
 
-		case OCONV<<16 | CTNIL_,
-			OARRAYBYTESTR<<16 | CTNIL_:
+		case OCONV_ | CTNIL_,
+			OARRAYBYTESTR_ | CTNIL_:
 			if n.Type.Etype == TSTRING {
 				v = tostr(v)
 				nl.Type = n.Type
@@ -632,24 +657,24 @@
 			fallthrough
 
 			// fall through
-		case OCONV<<16 | CTINT_,
-			OCONV<<16 | CTRUNE_,
-			OCONV<<16 | CTFLT_,
-			OCONV<<16 | CTSTR_:
+		case OCONV_ | CTINT_,
+			OCONV_ | CTRUNE_,
+			OCONV_ | CTFLT_,
+			OCONV_ | CTSTR_:
 			convlit1(&nl, n.Type, true)
 
 			v = nl.Val()
 
-		case OPLUS<<16 | CTINT_,
-			OPLUS<<16 | CTRUNE_:
+		case OPLUS_ | CTINT_,
+			OPLUS_ | CTRUNE_:
 			break
 
-		case OMINUS<<16 | CTINT_,
-			OMINUS<<16 | CTRUNE_:
+		case OMINUS_ | CTINT_,
+			OMINUS_ | CTRUNE_:
 			mpnegfix(v.U.(*Mpint))
 
-		case OCOM<<16 | CTINT_,
-			OCOM<<16 | CTRUNE_:
+		case OCOM_ | CTINT_,
+			OCOM_ | CTRUNE_:
 			et := Txxx
 			if nl.Type != nil {
 				et = int(nl.Type.Etype)
@@ -675,20 +700,20 @@
 
 			mpxorfixfix(v.U.(*Mpint), &b)
 
-		case OPLUS<<16 | CTFLT_:
+		case OPLUS_ | CTFLT_:
 			break
 
-		case OMINUS<<16 | CTFLT_:
+		case OMINUS_ | CTFLT_:
 			mpnegflt(v.U.(*Mpflt))
 
-		case OPLUS<<16 | CTCPLX_:
+		case OPLUS_ | CTCPLX_:
 			break
 
-		case OMINUS<<16 | CTCPLX_:
+		case OMINUS_ | CTCPLX_:
 			mpnegflt(&v.U.(*Mpcplx).Real)
 			mpnegflt(&v.U.(*Mpcplx).Imag)
 
-		case ONOT<<16 | CTBOOL_:
+		case ONOT_ | CTBOOL_:
 			if !v.U.(bool) {
 				goto settrue
 			}
@@ -799,20 +824,20 @@
 	default:
 		goto illegal
 
-	case OADD<<16 | CTINT_,
-		OADD<<16 | CTRUNE_:
+	case OADD_ | CTINT_,
+		OADD_ | CTRUNE_:
 		mpaddfixfix(v.U.(*Mpint), rv.U.(*Mpint), 0)
 
-	case OSUB<<16 | CTINT_,
-		OSUB<<16 | CTRUNE_:
+	case OSUB_ | CTINT_,
+		OSUB_ | CTRUNE_:
 		mpsubfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OMUL<<16 | CTINT_,
-		OMUL<<16 | CTRUNE_:
+	case OMUL_ | CTINT_,
+		OMUL_ | CTRUNE_:
 		mpmulfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case ODIV<<16 | CTINT_,
-		ODIV<<16 | CTRUNE_:
+	case ODIV_ | CTINT_,
+		ODIV_ | CTRUNE_:
 		if mpcmpfixc(rv.U.(*Mpint), 0) == 0 {
 			Yyerror("division by zero")
 			mpsetovf(v.U.(*Mpint))
@@ -821,8 +846,8 @@
 
 		mpdivfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OMOD<<16 | CTINT_,
-		OMOD<<16 | CTRUNE_:
+	case OMOD_ | CTINT_,
+		OMOD_ | CTRUNE_:
 		if mpcmpfixc(rv.U.(*Mpint), 0) == 0 {
 			Yyerror("division by zero")
 			mpsetovf(v.U.(*Mpint))
@@ -831,40 +856,40 @@
 
 		mpmodfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OLSH<<16 | CTINT_,
-		OLSH<<16 | CTRUNE_:
+	case OLSH_ | CTINT_,
+		OLSH_ | CTRUNE_:
 		mplshfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case ORSH<<16 | CTINT_,
-		ORSH<<16 | CTRUNE_:
+	case ORSH_ | CTINT_,
+		ORSH_ | CTRUNE_:
 		mprshfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OOR<<16 | CTINT_,
-		OOR<<16 | CTRUNE_:
+	case OOR_ | CTINT_,
+		OOR_ | CTRUNE_:
 		mporfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OAND<<16 | CTINT_,
-		OAND<<16 | CTRUNE_:
+	case OAND_ | CTINT_,
+		OAND_ | CTRUNE_:
 		mpandfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OANDNOT<<16 | CTINT_,
-		OANDNOT<<16 | CTRUNE_:
+	case OANDNOT_ | CTINT_,
+		OANDNOT_ | CTRUNE_:
 		mpandnotfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OXOR<<16 | CTINT_,
-		OXOR<<16 | CTRUNE_:
+	case OXOR_ | CTINT_,
+		OXOR_ | CTRUNE_:
 		mpxorfixfix(v.U.(*Mpint), rv.U.(*Mpint))
 
-	case OADD<<16 | CTFLT_:
+	case OADD_ | CTFLT_:
 		mpaddfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
 
-	case OSUB<<16 | CTFLT_:
+	case OSUB_ | CTFLT_:
 		mpsubfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
 
-	case OMUL<<16 | CTFLT_:
+	case OMUL_ | CTFLT_:
 		mpmulfltflt(v.U.(*Mpflt), rv.U.(*Mpflt))
 
-	case ODIV<<16 | CTFLT_:
+	case ODIV_ | CTFLT_:
 		if mpcmpfltc(rv.U.(*Mpflt), 0) == 0 {
 			Yyerror("division by zero")
 			Mpmovecflt(v.U.(*Mpflt), 1.0)
@@ -875,7 +900,7 @@
 
 		// The default case above would print 'ideal % ideal',
 	// which is not quite an ideal error.
-	case OMOD<<16 | CTFLT_:
+	case OMOD_ | CTFLT_:
 		if n.Diag == 0 {
 			Yyerror("illegal constant expression: floating-point %% operation")
 			n.Diag = 1
@@ -883,18 +908,18 @@
 
 		return
 
-	case OADD<<16 | CTCPLX_:
+	case OADD_ | CTCPLX_:
 		mpaddfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real)
 		mpaddfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag)
 
-	case OSUB<<16 | CTCPLX_:
+	case OSUB_ | CTCPLX_:
 		mpsubfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real)
 		mpsubfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag)
 
-	case OMUL<<16 | CTCPLX_:
+	case OMUL_ | CTCPLX_:
 		cmplxmpy(v.U.(*Mpcplx), rv.U.(*Mpcplx))
 
-	case ODIV<<16 | CTCPLX_:
+	case ODIV_ | CTCPLX_:
 		if mpcmpfltc(&rv.U.(*Mpcplx).Real, 0) == 0 && mpcmpfltc(&rv.U.(*Mpcplx).Imag, 0) == 0 {
 			Yyerror("complex division by zero")
 			Mpmovecflt(&rv.U.(*Mpcplx).Real, 1.0)
@@ -904,157 +929,157 @@
 
 		cmplxdiv(v.U.(*Mpcplx), rv.U.(*Mpcplx))
 
-	case OEQ<<16 | CTNIL_:
+	case OEQ_ | CTNIL_:
 		goto settrue
 
-	case ONE<<16 | CTNIL_:
+	case ONE_ | CTNIL_:
 		goto setfalse
 
-	case OEQ<<16 | CTINT_,
-		OEQ<<16 | CTRUNE_:
+	case OEQ_ | CTINT_,
+		OEQ_ | CTRUNE_:
 		if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) == 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case ONE<<16 | CTINT_,
-		ONE<<16 | CTRUNE_:
+	case ONE_ | CTINT_,
+		ONE_ | CTRUNE_:
 		if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) != 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OLT<<16 | CTINT_,
-		OLT<<16 | CTRUNE_:
+	case OLT_ | CTINT_,
+		OLT_ | CTRUNE_:
 		if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) < 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OLE<<16 | CTINT_,
-		OLE<<16 | CTRUNE_:
+	case OLE_ | CTINT_,
+		OLE_ | CTRUNE_:
 		if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) <= 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OGE<<16 | CTINT_,
-		OGE<<16 | CTRUNE_:
+	case OGE_ | CTINT_,
+		OGE_ | CTRUNE_:
 		if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) >= 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OGT<<16 | CTINT_,
-		OGT<<16 | CTRUNE_:
+	case OGT_ | CTINT_,
+		OGT_ | CTRUNE_:
 		if Mpcmpfixfix(v.U.(*Mpint), rv.U.(*Mpint)) > 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OEQ<<16 | CTFLT_:
+	case OEQ_ | CTFLT_:
 		if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) == 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case ONE<<16 | CTFLT_:
+	case ONE_ | CTFLT_:
 		if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) != 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OLT<<16 | CTFLT_:
+	case OLT_ | CTFLT_:
 		if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) < 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OLE<<16 | CTFLT_:
+	case OLE_ | CTFLT_:
 		if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) <= 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OGE<<16 | CTFLT_:
+	case OGE_ | CTFLT_:
 		if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) >= 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OGT<<16 | CTFLT_:
+	case OGT_ | CTFLT_:
 		if mpcmpfltflt(v.U.(*Mpflt), rv.U.(*Mpflt)) > 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OEQ<<16 | CTCPLX_:
+	case OEQ_ | CTCPLX_:
 		if mpcmpfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real) == 0 && mpcmpfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag) == 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case ONE<<16 | CTCPLX_:
+	case ONE_ | CTCPLX_:
 		if mpcmpfltflt(&v.U.(*Mpcplx).Real, &rv.U.(*Mpcplx).Real) != 0 || mpcmpfltflt(&v.U.(*Mpcplx).Imag, &rv.U.(*Mpcplx).Imag) != 0 {
 			goto settrue
 		}
 		goto setfalse
 
-	case OEQ<<16 | CTSTR_:
+	case OEQ_ | CTSTR_:
 		if strlit(nl) == strlit(nr) {
 			goto settrue
 		}
 		goto setfalse
 
-	case ONE<<16 | CTSTR_:
+	case ONE_ | CTSTR_:
 		if strlit(nl) != strlit(nr) {
 			goto settrue
 		}
 		goto setfalse
 
-	case OLT<<16 | CTSTR_:
+	case OLT_ | CTSTR_:
 		if strlit(nl) < strlit(nr) {
 			goto settrue
 		}
 		goto setfalse
 
-	case OLE<<16 | CTSTR_:
+	case OLE_ | CTSTR_:
 		if strlit(nl) <= strlit(nr) {
 			goto settrue
 		}
 		goto setfalse
 
-	case OGE<<16 | CTSTR_:
+	case OGE_ | CTSTR_:
 		if strlit(nl) >= strlit(nr) {
 			goto settrue
 		}
 		goto setfalse
 
-	case OGT<<16 | CTSTR_:
+	case OGT_ | CTSTR_:
 		if strlit(nl) > strlit(nr) {
 			goto settrue
 		}
 		goto setfalse
 
-	case OOROR<<16 | CTBOOL_:
+	case OOROR_ | CTBOOL_:
 		if v.U.(bool) || rv.U.(bool) {
 			goto settrue
 		}
 		goto setfalse
 
-	case OANDAND<<16 | CTBOOL_:
+	case OANDAND_ | CTBOOL_:
 		if v.U.(bool) && rv.U.(bool) {
 			goto settrue
 		}
 		goto setfalse
 
-	case OEQ<<16 | CTBOOL_:
+	case OEQ_ | CTBOOL_:
 		if v.U.(bool) == rv.U.(bool) {
 			goto settrue
 		}
 		goto setfalse
 
-	case ONE<<16 | CTBOOL_:
+	case ONE_ | CTBOOL_:
 		if v.U.(bool) != rv.U.(bool) {
 			goto settrue
 		}
@@ -1406,7 +1431,7 @@
 
 // convert x to type et and back to int64
 // for sign extension and truncation.
-func iconv(x int64, et int) int64 {
+func iconv(x int64, et EType) int64 {
 	switch et {
 	case TINT8:
 		x = int64(int8(x))
diff --git a/src/cmd/compile/internal/gc/cplx.go b/src/cmd/compile/internal/gc/cplx.go
index 9f11b96..b692456 100644
--- a/src/cmd/compile/internal/gc/cplx.go
+++ b/src/cmd/compile/internal/gc/cplx.go
@@ -14,7 +14,7 @@
 	return f.Op == OINDREG && t.Op == OINDREG && f.Xoffset+f.Type.Width >= t.Xoffset && t.Xoffset+t.Type.Width >= f.Xoffset
 }
 
-func complexbool(op int, nl, nr, res *Node, wantTrue bool, likely int, to *obj.Prog) {
+func complexbool(op Op, nl, nr, res *Node, wantTrue bool, likely int, to *obj.Prog) {
 	// make both sides addable in ullman order
 	if nr != nil {
 		if nl.Ullman > nr.Ullman && !nl.Addable {
@@ -130,7 +130,7 @@
 // build and execute tree
 //	real(res) = real(nl) op real(nr)
 //	imag(res) = imag(nl) op imag(nr)
-func complexadd(op int, nl *Node, nr *Node, res *Node) {
+func complexadd(op Op, nl *Node, nr *Node, res *Node) {
 	var n1 Node
 	var n2 Node
 	var n3 Node
@@ -143,14 +143,14 @@
 	subnode(&n5, &n6, res)
 
 	var ra Node
-	ra.Op = uint8(op)
+	ra.Op = op
 	ra.Left = &n1
 	ra.Right = &n3
 	ra.Type = n1.Type
 	Cgen(&ra, &n5)
 
 	ra = Node{}
-	ra.Op = uint8(op)
+	ra.Op = op
 	ra.Left = &n2
 	ra.Right = &n4
 	ra.Type = n2.Type
@@ -293,17 +293,10 @@
 
 	ft := Simsimtype(f.Type)
 	tt := Simsimtype(t.Type)
-	switch uint32(ft)<<16 | uint32(tt) {
-	default:
-		Fatalf("complexmove: unknown conversion: %v -> %v\n", f.Type, t.Type)
-
-		// complex to complex move/convert.
+	// complex to complex move/convert.
 	// make f addable.
 	// also use temporary if possible stack overlap.
-	case TCOMPLEX64<<16 | TCOMPLEX64,
-		TCOMPLEX64<<16 | TCOMPLEX128,
-		TCOMPLEX128<<16 | TCOMPLEX64,
-		TCOMPLEX128<<16 | TCOMPLEX128:
+	if (ft == TCOMPLEX64 || ft == TCOMPLEX128) && (tt == TCOMPLEX64 || tt == TCOMPLEX128) {
 		if !f.Addable || overlap_cplx(f, t) {
 			var tmp Node
 			Tempname(&tmp, f.Type)
@@ -320,6 +313,8 @@
 
 		Cgen(&n1, &n3)
 		Cgen(&n2, &n4)
+	} else {
+		Fatalf("complexmove: unknown conversion: %v -> %v\n", f.Type, t.Type)
 	}
 }
 
@@ -471,7 +466,7 @@
 		complexminus(nl, res)
 
 	case OADD, OSUB:
-		complexadd(int(n.Op), nl, nr, res)
+		complexadd(n.Op, nl, nr, res)
 
 	case OMUL:
 		complexmul(nl, nr, res)
diff --git a/src/cmd/compile/internal/gc/export.go b/src/cmd/compile/internal/gc/export.go
index a7a8522..b4182ae 100644
--- a/src/cmd/compile/internal/gc/export.go
+++ b/src/cmd/compile/internal/gc/export.go
@@ -434,8 +434,8 @@
 // import
 
 // return the sym for ss, which should match lexical
-func importsym(s *Sym, op int) *Sym {
-	if s.Def != nil && int(s.Def.Op) != op {
+func importsym(s *Sym, op Op) *Sym {
+	if s.Def != nil && s.Def.Op != op {
 		pkgstr := fmt.Sprintf("during import %q", importpkg.Path)
 		redeclare(s, pkgstr)
 	}
diff --git a/src/cmd/compile/internal/gc/fmt.go b/src/cmd/compile/internal/gc/fmt.go
index 221e4a6..2525921 100644
--- a/src/cmd/compile/internal/gc/fmt.go
+++ b/src/cmd/compile/internal/gc/fmt.go
@@ -400,8 +400,8 @@
 }
 
 // Fmt "%E": etype
-func Econv(et int, flag int) string {
-	if et >= 0 && et < len(etnames) && etnames[et] != "" {
+func Econv(et EType) string {
+	if int(et) < len(etnames) && etnames[et] != "" {
 		return etnames[et]
 	}
 	return fmt.Sprintf("E-%d", et)
@@ -536,7 +536,7 @@
 
 	if fmtmode == FDbg {
 		fmtmode = 0
-		str := Econv(int(t.Etype), 0) + "-" + typefmt(t, flag)
+		str := Econv(t.Etype) + "-" + typefmt(t, flag)
 		fmtmode = FDbg
 		return str
 	}
@@ -755,15 +755,15 @@
 	}
 
 	if fmtmode == FExp {
-		Fatalf("missing %v case during export", Econv(int(t.Etype), 0))
+		Fatalf("missing %v case during export", Econv(t.Etype))
 	}
 
 	// Don't know how to handle - fall back to detailed prints.
-	return fmt.Sprintf("%v <%v> %v", Econv(int(t.Etype), 0), t.Sym, t.Type)
+	return fmt.Sprintf("%v <%v> %v", Econv(t.Etype), t.Sym, t.Type)
 }
 
 // Statements which may be rendered with a simplestmt as init.
-func stmtwithinit(op int) bool {
+func stmtwithinit(op Op) bool {
 	switch op {
 	case OIF, OFOR, OSWITCH:
 		return true
@@ -781,13 +781,13 @@
 	// block starting with the init statements.
 
 	// if we can just say "for" n->ninit; ... then do so
-	simpleinit := n.Ninit != nil && n.Ninit.Next == nil && n.Ninit.N.Ninit == nil && stmtwithinit(int(n.Op))
+	simpleinit := n.Ninit != nil && n.Ninit.Next == nil && n.Ninit.N.Ninit == nil && stmtwithinit(n.Op)
 
 	// otherwise, print the inits as separate statements
 	complexinit := n.Ninit != nil && !simpleinit && (fmtmode != FErr)
 
 	// but if it was for if/for/switch, put in an extra surrounding block to limit the scope
-	extrablock := complexinit && stmtwithinit(int(n.Op))
+	extrablock := complexinit && stmtwithinit(n.Op)
 
 	if extrablock {
 		f += "{"
@@ -832,7 +832,7 @@
 
 	case OASOP:
 		if n.Implicit {
-			if n.Etype == OADD {
+			if Op(n.Etype) == OADD {
 				f += fmt.Sprintf("%v++", n.Left)
 			} else {
 				f += fmt.Sprintf("%v--", n.Left)
@@ -1442,6 +1442,7 @@
 	case OCMPSTR, OCMPIFACE:
 		var f string
 		f += exprfmt(n.Left, nprec)
+		// TODO(marvin): Fix Node.EType type union.
 		f += fmt.Sprintf(" %v ", Oconv(int(n.Etype), obj.FmtSharp))
 		f += exprfmt(n.Right, nprec+1)
 		return f
diff --git a/src/cmd/compile/internal/gc/gen.go b/src/cmd/compile/internal/gc/gen.go
index a222185..27737b7 100644
--- a/src/cmd/compile/internal/gc/gen.go
+++ b/src/cmd/compile/internal/gc/gen.go
@@ -1012,7 +1012,7 @@
 	numPtr := 0
 	visitComponents(nl.Type, 0, func(t *Type, offset int64) bool {
 		n++
-		if int(Simtype[t.Etype]) == Tptr && t != itable {
+		if Simtype[t.Etype] == Tptr && t != itable {
 			numPtr++
 		}
 		return n <= maxMoves && (!wb || numPtr <= 1)
@@ -1129,7 +1129,7 @@
 		ptrOffset int64
 	)
 	visitComponents(nl.Type, 0, func(t *Type, offset int64) bool {
-		if wb && int(Simtype[t.Etype]) == Tptr && t != itable {
+		if wb && Simtype[t.Etype] == Tptr && t != itable {
 			if ptrType != nil {
 				Fatalf("componentgen_wb %v", Tconv(nl.Type, 0))
 			}
diff --git a/src/cmd/compile/internal/gc/go.go b/src/cmd/compile/internal/gc/go.go
index 84f11e6..4ccf360 100644
--- a/src/cmd/compile/internal/gc/go.go
+++ b/src/cmd/compile/internal/gc/go.go
@@ -151,7 +151,7 @@
 }
 
 type Type struct {
-	Etype       uint8
+	Etype       EType
 	Nointerface bool
 	Noalg       bool
 	Chan        uint8
@@ -258,6 +258,8 @@
 	T     *Type
 }
 
+type EType uint8
+
 const (
 	Txxx = iota
 
@@ -369,8 +371,8 @@
 
 type Typedef struct {
 	Name   string
-	Etype  int
-	Sameas int
+	Etype  EType
+	Sameas EType
 }
 
 type Sig struct {
@@ -522,7 +524,7 @@
 
 var trackpkg *Pkg // fake package for field tracking
 
-var Tptr int // either TPTR32 or TPTR64
+var Tptr EType // either TPTR32 or TPTR64
 
 var myimportpath string
 
@@ -544,7 +546,7 @@
 
 var errortype *Type
 
-var Simtype [NTYPE]uint8
+var Simtype [NTYPE]EType
 
 var (
 	Isptr     [NTYPE]bool
@@ -792,14 +794,14 @@
 	Bgen_float   func(*Node, bool, int, *obj.Prog) // optional
 	Cgen64       func(*Node, *Node)                // only on 32-bit systems
 	Cgenindex    func(*Node, *Node, bool) *obj.Prog
-	Cgen_bmul    func(int, *Node, *Node, *Node) bool
+	Cgen_bmul    func(Op, *Node, *Node, *Node) bool
 	Cgen_float   func(*Node, *Node) // optional
 	Cgen_hmul    func(*Node, *Node, *Node)
-	Cgen_shift   func(int, bool, *Node, *Node, *Node)
+	Cgen_shift   func(Op, bool, *Node, *Node, *Node)
 	Clearfat     func(*Node)
-	Cmp64        func(*Node, *Node, int, int, *obj.Prog) // only on 32-bit systems
+	Cmp64        func(*Node, *Node, Op, int, *obj.Prog) // only on 32-bit systems
 	Defframe     func(*obj.Prog)
-	Dodiv        func(int, *Node, *Node, *Node)
+	Dodiv        func(Op, *Node, *Node, *Node)
 	Excise       func(*Flow)
 	Expandchecks func(*obj.Prog)
 	Getg         func(*Node)
@@ -815,7 +817,7 @@
 	// function calls needed during the evaluation, and on 32-bit systems
 	// the values are guaranteed not to be 64-bit values, so no in-memory
 	// temporaries are necessary.
-	Ginscmp func(op int, t *Type, n1, n2 *Node, likely int) *obj.Prog
+	Ginscmp func(op Op, t *Type, n1, n2 *Node, likely int) *obj.Prog
 
 	// Ginsboolval inserts instructions to convert the result
 	// of a just-completed comparison to a boolean value.
@@ -844,7 +846,7 @@
 	FtoB         func(int) uint64
 	BtoR         func(uint64) int
 	BtoF         func(uint64) int
-	Optoas       func(int, *Type) int
+	Optoas       func(Op, *Type) int
 	Doregbits    func(int) uint64
 	Regnames     func(*int) []string
 	Use387       bool // should 8g use 387 FP instructions instead of sse2.
diff --git a/src/cmd/compile/internal/gc/go.y b/src/cmd/compile/internal/gc/go.y
index fc3af69..5e56763 100644
--- a/src/cmd/compile/internal/gc/go.y
+++ b/src/cmd/compile/internal/gc/go.y
@@ -488,7 +488,7 @@
 |	expr LASOP expr
 	{
 		$$ = Nod(OASOP, $1, $3);
-		$$.Etype = uint8($2);			// rathole to pass opcode
+		$$.Etype = EType($2);			// rathole to pass opcode
 	}
 |	expr_list '=' expr_list
 	{
@@ -524,13 +524,15 @@
 	{
 		$$ = Nod(OASOP, $1, Nodintconst(1));
 		$$.Implicit = true;
-		$$.Etype = OADD;
+		// TODO(marvin): Fix Node.EType type union.
+		$$.Etype = EType(OADD);
 	}
 |	expr LDEC
 	{
 		$$ = Nod(OASOP, $1, Nodintconst(1));
 		$$.Implicit = true;
-		$$.Etype = OSUB;
+		// TODO(marvin): Fix Node.EType type union.
+		$$.Etype = EType(OSUB);
 	}
 
 case:
diff --git a/src/cmd/compile/internal/gc/gsubr.go b/src/cmd/compile/internal/gc/gsubr.go
index 2547cb3..6b11ed2 100644
--- a/src/cmd/compile/internal/gc/gsubr.go
+++ b/src/cmd/compile/internal/gc/gsubr.go
@@ -335,7 +335,7 @@
 		// n->left is PHEAP ONAME for stack parameter.
 	// compute address of actual parameter on stack.
 	case OPARAM:
-		a.Etype = Simtype[n.Left.Type.Etype]
+		a.Etype = uint8(Simtype[n.Left.Type.Etype])
 
 		a.Width = n.Left.Type.Width
 		a.Offset = n.Xoffset
@@ -360,7 +360,7 @@
 	case ONAME:
 		a.Etype = 0
 		if n.Type != nil {
-			a.Etype = Simtype[n.Type.Etype]
+			a.Etype = uint8(Simtype[n.Type.Etype])
 		}
 		a.Offset = n.Xoffset
 		s := n.Sym
@@ -464,7 +464,7 @@
 		if a.Type == obj.TYPE_CONST && a.Offset == 0 {
 			break // ptr(nil)
 		}
-		a.Etype = Simtype[Tptr]
+		a.Etype = uint8(Simtype[Tptr])
 		a.Offset += int64(Array_array)
 		a.Width = int64(Widthptr)
 
@@ -475,7 +475,7 @@
 		if a.Type == obj.TYPE_CONST && a.Offset == 0 {
 			break // len(nil)
 		}
-		a.Etype = Simtype[TUINT]
+		a.Etype = uint8(Simtype[TUINT])
 		a.Offset += int64(Array_nel)
 		if Thearch.Thechar != '5' { // TODO(rsc): Do this even on arm.
 			a.Width = int64(Widthint)
@@ -488,7 +488,7 @@
 		if a.Type == obj.TYPE_CONST && a.Offset == 0 {
 			break // cap(nil)
 		}
-		a.Etype = Simtype[TUINT]
+		a.Etype = uint8(Simtype[TUINT])
 		a.Offset += int64(Array_cap)
 		if Thearch.Thechar != '5' { // TODO(rsc): Do this even on arm.
 			a.Width = int64(Widthint)
@@ -667,7 +667,7 @@
 	if t == nil {
 		Fatalf("regalloc: t nil")
 	}
-	et := int(Simtype[t.Etype])
+	et := Simtype[t.Etype]
 	if Ctxt.Arch.Regsize == 4 && (et == TINT64 || et == TUINT64) {
 		Fatalf("regalloc 64bit")
 	}
diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go
index 66d5b74..64afd67 100644
--- a/src/cmd/compile/internal/gc/inl.go
+++ b/src/cmd/compile/internal/gc/inl.go
@@ -350,7 +350,8 @@
 	case ODEFER, OPROC:
 		switch n.Left.Op {
 		case OCALLFUNC, OCALLMETH:
-			n.Left.Etype = n.Op
+			// TODO(marvin): Fix Node.EType type union.
+			n.Left.Etype = EType(n.Op)
 		}
 		fallthrough
 
@@ -450,7 +451,8 @@
 	// switch at the top of this function.
 	switch n.Op {
 	case OCALLFUNC, OCALLMETH:
-		if n.Etype == OPROC || n.Etype == ODEFER {
+		// TODO(marvin): Fix Node.EType type union.
+		if n.Etype == EType(OPROC) || n.Etype == EType(ODEFER) {
 			return
 		}
 	}
diff --git a/src/cmd/compile/internal/gc/lex.go b/src/cmd/compile/internal/gc/lex.go
index cd964ff..c7a16e8 100644
--- a/src/cmd/compile/internal/gc/lex.go
+++ b/src/cmd/compile/internal/gc/lex.go
@@ -1187,14 +1187,14 @@
 		}
 
 		if c1 == '=' {
-			c = ODIV
+			c = int(ODIV)
 			goto asop
 		}
 
 	case ':':
 		c1 = getc()
 		if c1 == '=' {
-			c = LCOLAS
+			c = int(LCOLAS)
 			yylval.i = int(lexlineno)
 			goto lx
 		}
@@ -1202,48 +1202,48 @@
 	case '*':
 		c1 = getc()
 		if c1 == '=' {
-			c = OMUL
+			c = int(OMUL)
 			goto asop
 		}
 
 	case '%':
 		c1 = getc()
 		if c1 == '=' {
-			c = OMOD
+			c = int(OMOD)
 			goto asop
 		}
 
 	case '+':
 		c1 = getc()
 		if c1 == '+' {
-			c = LINC
+			c = int(LINC)
 			goto lx
 		}
 
 		if c1 == '=' {
-			c = OADD
+			c = int(OADD)
 			goto asop
 		}
 
 	case '-':
 		c1 = getc()
 		if c1 == '-' {
-			c = LDEC
+			c = int(LDEC)
 			goto lx
 		}
 
 		if c1 == '=' {
-			c = OSUB
+			c = int(OSUB)
 			goto asop
 		}
 
 	case '>':
 		c1 = getc()
 		if c1 == '>' {
-			c = LRSH
+			c = int(LRSH)
 			c1 = getc()
 			if c1 == '=' {
-				c = ORSH
+				c = int(ORSH)
 				goto asop
 			}
 
@@ -1251,19 +1251,19 @@
 		}
 
 		if c1 == '=' {
-			c = LGE
+			c = int(LGE)
 			goto lx
 		}
 
-		c = LGT
+		c = int(LGT)
 
 	case '<':
 		c1 = getc()
 		if c1 == '<' {
-			c = LLSH
+			c = int(LLSH)
 			c1 = getc()
 			if c1 == '=' {
-				c = OLSH
+				c = int(OLSH)
 				goto asop
 			}
 
@@ -1271,43 +1271,43 @@
 		}
 
 		if c1 == '=' {
-			c = LLE
+			c = int(LLE)
 			goto lx
 		}
 
 		if c1 == '-' {
-			c = LCOMM
+			c = int(LCOMM)
 			goto lx
 		}
 
-		c = LLT
+		c = int(LLT)
 
 	case '=':
 		c1 = getc()
 		if c1 == '=' {
-			c = LEQ
+			c = int(LEQ)
 			goto lx
 		}
 
 	case '!':
 		c1 = getc()
 		if c1 == '=' {
-			c = LNE
+			c = int(LNE)
 			goto lx
 		}
 
 	case '&':
 		c1 = getc()
 		if c1 == '&' {
-			c = LANDAND
+			c = int(LANDAND)
 			goto lx
 		}
 
 		if c1 == '^' {
-			c = LANDNOT
+			c = int(LANDNOT)
 			c1 = getc()
 			if c1 == '=' {
-				c = OANDNOT
+				c = int(OANDNOT)
 				goto asop
 			}
 
@@ -1315,26 +1315,26 @@
 		}
 
 		if c1 == '=' {
-			c = OAND
+			c = int(OAND)
 			goto asop
 		}
 
 	case '|':
 		c1 = getc()
 		if c1 == '|' {
-			c = LOROR
+			c = int(LOROR)
 			goto lx
 		}
 
 		if c1 == '=' {
-			c = OOR
+			c = int(OOR)
 			goto asop
 		}
 
 	case '^':
 		c1 = getc()
 		if c1 == '=' {
-			c = OXOR
+			c = int(OXOR)
 			goto asop
 		}
 
@@ -2159,8 +2159,8 @@
 var syms = []struct {
 	name    string
 	lexical int
-	etype   int
-	op      int
+	etype   EType
+	op      Op
 }{
 	// basic types
 	{"int8", LNAME, TINT8, OXXX},
@@ -2233,7 +2233,7 @@
 		s1.Lexical = uint16(lex)
 
 		if etype := s.etype; etype != Txxx {
-			if etype < 0 || etype >= len(Types) {
+			if int(etype) >= len(Types) {
 				Fatalf("lexinit: %s bad etype", s.name)
 			}
 			s2 := Pkglookup(s.name, builtinpkg)
@@ -2254,12 +2254,13 @@
 			continue
 		}
 
+		// TODO(marvin): Fix Node.EType type union.
 		if etype := s.op; etype != OXXX {
 			s2 := Pkglookup(s.name, builtinpkg)
 			s2.Lexical = LNAME
 			s2.Def = Nod(ONAME, nil, nil)
 			s2.Def.Sym = s2
-			s2.Def.Etype = uint8(etype)
+			s2.Def.Etype = EType(etype)
 		}
 	}
 
@@ -2368,38 +2369,34 @@
 }
 
 func lexfini() {
-	var s *Sym
-	var lex int
-	var etype int
-	var i int
-
-	for i = 0; i < len(syms); i++ {
-		lex = syms[i].lexical
+	for i := range syms {
+		lex := syms[i].lexical
 		if lex != LNAME {
 			continue
 		}
-		s = Lookup(syms[i].name)
+		s := Lookup(syms[i].name)
 		s.Lexical = uint16(lex)
 
-		etype = syms[i].etype
+		etype := syms[i].etype
 		if etype != Txxx && (etype != TANY || Debug['A'] != 0) && s.Def == nil {
 			s.Def = typenod(Types[etype])
 			s.Def.Name = new(Name)
 			s.Origpkg = builtinpkg
 		}
 
-		etype = syms[i].op
-		if etype != OXXX && s.Def == nil {
+		// TODO(marvin): Fix Node.EType type union.
+		etype = EType(syms[i].op)
+		if etype != EType(OXXX) && s.Def == nil {
 			s.Def = Nod(ONAME, nil, nil)
 			s.Def.Sym = s
-			s.Def.Etype = uint8(etype)
+			s.Def.Etype = etype
 			s.Origpkg = builtinpkg
 		}
 	}
 
 	// backend-specific builtin types (e.g. int).
-	for i = range Thearch.Typedefs {
-		s = Lookup(Thearch.Typedefs[i].Name)
+	for i := range Thearch.Typedefs {
+		s := Lookup(Thearch.Typedefs[i].Name)
 		if s.Def == nil {
 			s.Def = typenod(Types[Thearch.Typedefs[i].Etype])
 			s.Def.Name = new(Name)
@@ -2409,30 +2406,25 @@
 
 	// there's only so much table-driven we can handle.
 	// these are special cases.
-	s = Lookup("byte")
-
-	if s.Def == nil {
+	if s := Lookup("byte"); s.Def == nil {
 		s.Def = typenod(bytetype)
 		s.Def.Name = new(Name)
 		s.Origpkg = builtinpkg
 	}
 
-	s = Lookup("error")
-	if s.Def == nil {
+	if s := Lookup("error"); s.Def == nil {
 		s.Def = typenod(errortype)
 		s.Def.Name = new(Name)
 		s.Origpkg = builtinpkg
 	}
 
-	s = Lookup("rune")
-	if s.Def == nil {
+	if s := Lookup("rune"); s.Def == nil {
 		s.Def = typenod(runetype)
 		s.Def.Name = new(Name)
 		s.Origpkg = builtinpkg
 	}
 
-	s = Lookup("nil")
-	if s.Def == nil {
+	if s := Lookup("nil"); s.Def == nil {
 		var v Val
 		v.U = new(NilVal)
 		s.Def = nodlit(v)
@@ -2441,23 +2433,20 @@
 		s.Origpkg = builtinpkg
 	}
 
-	s = Lookup("iota")
-	if s.Def == nil {
+	if s := Lookup("iota"); s.Def == nil {
 		s.Def = Nod(OIOTA, nil, nil)
 		s.Def.Sym = s
 		s.Origpkg = builtinpkg
 	}
 
-	s = Lookup("true")
-	if s.Def == nil {
+	if s := Lookup("true"); s.Def == nil {
 		s.Def = Nodbool(true)
 		s.Def.Sym = s
 		s.Def.Name = new(Name)
 		s.Origpkg = builtinpkg
 	}
 
-	s = Lookup("false")
-	if s.Def == nil {
+	if s := Lookup("false"); s.Def == nil {
 		s.Def = Nodbool(false)
 		s.Def.Sym = s
 		s.Def.Name = new(Name)
diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go
index d65e3ba6..66549be 100644
--- a/src/cmd/compile/internal/gc/obj.go
+++ b/src/cmd/compile/internal/gc/obj.go
@@ -277,7 +277,7 @@
 	a.Sym = Linksym(symdata)
 	a.Node = symdata.Def
 	a.Offset = 0
-	a.Etype = Simtype[TINT]
+	a.Etype = uint8(Simtype[TINT])
 }
 
 func datagostring(sval string, a *obj.Addr) {
@@ -287,7 +287,7 @@
 	a.Sym = Linksym(symhdr)
 	a.Node = symhdr.Def
 	a.Offset = 0
-	a.Etype = TSTRING
+	a.Etype = uint8(TSTRING)
 }
 
 func dgostringptr(s *Sym, off int, str string) int {
@@ -312,7 +312,7 @@
 	p.From3.Offset = int64(Widthptr)
 	datagostring(*lit, &p.To)
 	p.To.Type = obj.TYPE_ADDR
-	p.To.Etype = Simtype[TINT]
+	p.To.Etype = uint8(Simtype[TINT])
 	off += Widthptr
 
 	return off
@@ -373,8 +373,8 @@
 }
 
 func gdatacomplex(nam *Node, cval *Mpcplx) {
-	w := cplxsubtype(int(nam.Type.Etype))
-	w = int(Types[w].Width)
+	cst := cplxsubtype(nam.Type.Etype)
+	w := int(Types[cst].Width)
 
 	p := Thearch.Gins(obj.ADATA, nam, nil)
 	p.From3 = new(obj.Addr)
diff --git a/src/cmd/compile/internal/gc/order.go b/src/cmd/compile/internal/gc/order.go
index 7e052c1..d01539e 100644
--- a/src/cmd/compile/internal/gc/order.go
+++ b/src/cmd/compile/internal/gc/order.go
@@ -509,7 +509,8 @@
 			tmp1.Etype = 0 // now an rvalue not an lvalue
 		}
 		tmp1 = ordercopyexpr(tmp1, n.Left.Type, order, 0)
-		n.Right = Nod(int(n.Etype), tmp1, n.Right)
+		// TODO(marvin): Fix Node.EType type union.
+		n.Right = Nod(Op(n.Etype), tmp1, n.Right)
 		typecheck(&n.Right, Erv)
 		orderexpr(&n.Right, order, nil)
 		n.Etype = 0
diff --git a/src/cmd/compile/internal/gc/reflect.go b/src/cmd/compile/internal/gc/reflect.go
index d1b18ff..308d0de 100644
--- a/src/cmd/compile/internal/gc/reflect.go
+++ b/src/cmd/compile/internal/gc/reflect.go
@@ -1267,7 +1267,7 @@
 	// another possible choice would be package main,
 	// but using runtime means fewer copies in .6 files.
 	if compiling_runtime != 0 {
-		for i := 1; i <= TBOOL; i++ {
+		for i := EType(1); i <= TBOOL; i++ {
 			dtypesym(Ptrto(Types[i]))
 		}
 		dtypesym(Ptrto(Types[TSTRING]))
diff --git a/src/cmd/compile/internal/gc/reg.go b/src/cmd/compile/internal/gc/reg.go
index 8ae4633..b4ef9931 100644
--- a/src/cmd/compile/internal/gc/reg.go
+++ b/src/cmd/compile/internal/gc/reg.go
@@ -48,7 +48,7 @@
 	width      int
 	id         int // index in vars
 	name       int8
-	etype      int8
+	etype      EType
 	addr       int8
 }
 
@@ -352,7 +352,7 @@
 	if node.Sym == nil || node.Sym.Name[0] == '.' {
 		return zbits
 	}
-	et := int(a.Etype)
+	et := EType(a.Etype)
 	o := a.Offset
 	w := a.Width
 	if w < 0 {
@@ -365,7 +365,7 @@
 		v = &vars[i]
 		if v.node == node && int(v.name) == n {
 			if v.offset == o {
-				if int(v.etype) == et {
+				if v.etype == et {
 					if int64(v.width) == w {
 						// TODO(rsc): Remove special case for arm here.
 						if flag == 0 || Thearch.Thechar != '5' {
@@ -419,7 +419,7 @@
 	v.id = i
 	v.offset = o
 	v.name = int8(n)
-	v.etype = int8(et)
+	v.etype = et
 	v.width = int(w)
 	v.addr = int8(flag) // funny punning
 	v.node = node
@@ -487,7 +487,7 @@
 	}
 
 	if Debug['R'] != 0 {
-		fmt.Printf("bit=%2d et=%v w=%d+%d %v %v flag=%d\n", i, Econv(int(et), 0), o, w, Nconv(node, obj.FmtSharp), Ctxt.Dconv(a), v.addr)
+		fmt.Printf("bit=%2d et=%v w=%d+%d %v %v flag=%d\n", i, Econv(et), o, w, Nconv(node, obj.FmtSharp), Ctxt.Dconv(a), v.addr)
 	}
 	Ostats.Nvar++
 
@@ -651,7 +651,7 @@
 	r.regno = 0
 	switch v.etype {
 	default:
-		Fatalf("unknown etype %d/%v", Bitno(b), Econv(int(v.etype), 0))
+		Fatalf("unknown etype %d/%v", Bitno(b), Econv(v.etype))
 
 	case TINT8,
 		TUINT8,
@@ -1143,7 +1143,7 @@
 		}
 
 		if Debug['R'] != 0 && Debug['v'] != 0 {
-			fmt.Printf("bit=%2d addr=%d et=%v w=%-2d s=%v + %d\n", i, v.addr, Econv(int(v.etype), 0), v.width, v.node, v.offset)
+			fmt.Printf("bit=%2d addr=%d et=%v w=%-2d s=%v + %d\n", i, v.addr, Econv(v.etype), v.width, v.node, v.offset)
 		}
 	}
 
@@ -1357,7 +1357,7 @@
 		if rgp.regno != 0 {
 			if Debug['R'] != 0 && Debug['v'] != 0 {
 				v := &vars[rgp.varno]
-				fmt.Printf("registerize %v+%d (bit=%2d et=%v) in %v usedreg=%#x vreg=%#x\n", v.node, v.offset, rgp.varno, Econv(int(v.etype), 0), obj.Rconv(int(rgp.regno)), usedreg, vreg)
+				fmt.Printf("registerize %v+%d (bit=%2d et=%v) in %v usedreg=%#x vreg=%#x\n", v.node, v.offset, rgp.varno, Econv(v.etype), obj.Rconv(int(rgp.regno)), usedreg, vreg)
 			}
 
 			paint3(rgp.enter, int(rgp.varno), vreg, int(rgp.regno))
diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go
index ca8a89c..6bc4bc8 100644
--- a/src/cmd/compile/internal/gc/subr.go
+++ b/src/cmd/compile/internal/gc/subr.go
@@ -347,9 +347,9 @@
 	}
 }
 
-func Nod(op int, nleft *Node, nright *Node) *Node {
+func Nod(op Op, nleft *Node, nright *Node) *Node {
 	n := new(Node)
-	n.Op = uint8(op)
+	n.Op = op
 	n.Left = nleft
 	n.Right = nright
 	n.Lineno = int32(parserline())
@@ -382,7 +382,7 @@
 	if n.Orig != nil {
 		return
 	}
-	norig := Nod(int(n.Op), nil, nil)
+	norig := Nod(n.Op, nil, nil)
 	*norig = *n
 	n.Orig = norig
 }
@@ -546,11 +546,11 @@
 	if key != nil {
 		var bad *Type
 		atype := algtype1(key, &bad)
-		var mtype int
+		var mtype EType
 		if bad == nil {
-			mtype = int(key.Etype)
+			mtype = key.Etype
 		} else {
-			mtype = int(bad.Etype)
+			mtype = bad.Etype
 		}
 		switch mtype {
 		default:
@@ -581,9 +581,9 @@
 	return t
 }
 
-func typ(et int) *Type {
+func typ(et EType) *Type {
 	t := new(Type)
-	t.Etype = uint8(et)
+	t.Etype = et
 	t.Width = BADWIDTH
 	t.Lineno = int(lineno)
 	t.Orig = t
@@ -777,7 +777,7 @@
 	return true
 }
 
-func isptrto(t *Type, et int) bool {
+func isptrto(t *Type, et EType) bool {
 	if t == nil {
 		return false
 	}
@@ -788,14 +788,14 @@
 	if t == nil {
 		return false
 	}
-	if int(t.Etype) != et {
+	if t.Etype != et {
 		return false
 	}
 	return true
 }
 
-func Istype(t *Type, et int) bool {
-	return t != nil && int(t.Etype) == et
+func Istype(t *Type, et EType) bool {
+	return t != nil && t.Etype == et
 }
 
 func Isfixedarray(t *Type) bool {
@@ -888,7 +888,7 @@
 	return t
 }
 
-func cplxsubtype(et int) int {
+func cplxsubtype(et EType) EType {
 	switch et {
 	case TCOMPLEX64:
 		return TFLOAT32
@@ -897,7 +897,7 @@
 		return TFLOAT64
 	}
 
-	Fatalf("cplxsubtype: %v\n", Econv(int(et), 0))
+	Fatalf("cplxsubtype: %v\n", Econv(et))
 	return 0
 }
 
@@ -1054,7 +1054,7 @@
 // Is type src assignment compatible to type dst?
 // If so, return op code to use in conversion.
 // If not, return 0.
-func assignop(src *Type, dst *Type, why *string) int {
+func assignop(src *Type, dst *Type, why *string) Op {
 	if why != nil {
 		*why = ""
 	}
@@ -1178,7 +1178,7 @@
 // Can we convert a value of type src to a value of type dst?
 // If so, return op code to use in conversion (maybe OCONVNOP).
 // If not, return 0.
-func convertop(src *Type, dst *Type, why *string) int {
+func convertop(src *Type, dst *Type, why *string) Op {
 	if why != nil {
 		*why = ""
 	}
@@ -1396,8 +1396,8 @@
 
 // Is a conversion between t1 and t2 a no-op?
 func Noconv(t1 *Type, t2 *Type) bool {
-	e1 := int(Simtype[t1.Etype])
-	e2 := int(Simtype[t2.Etype])
+	e1 := Simtype[t1.Etype]
+	e2 := Simtype[t2.Etype]
 
 	switch e1 {
 	case TINT8, TUINT8:
@@ -1663,7 +1663,7 @@
 	n.Ullman = uint8(ul)
 }
 
-func badtype(o int, tl *Type, tr *Type) {
+func badtype(op Op, tl *Type, tr *Type) {
 	fmt_ := ""
 	if tl != nil {
 		fmt_ += fmt.Sprintf("\n\t%v", tl)
@@ -1682,7 +1682,7 @@
 	}
 
 	s := fmt_
-	Yyerror("illegal types for operand: %v%s", Oconv(int(o), 0), s)
+	Yyerror("illegal types for operand: %v%s", Oconv(int(op), 0), s)
 }
 
 // iterator to walk a structure declaration
@@ -1809,8 +1809,8 @@
 
 // Brcom returns !(op).
 // For example, Brcom(==) is !=.
-func Brcom(a int) int {
-	switch a {
+func Brcom(op Op) Op {
+	switch op {
 	case OEQ:
 		return ONE
 	case ONE:
@@ -1824,14 +1824,14 @@
 	case OGE:
 		return OLT
 	}
-	Fatalf("brcom: no com for %v\n", Oconv(a, 0))
-	return a
+	Fatalf("brcom: no com for %v\n", Oconv(int(op), 0))
+	return op
 }
 
 // Brrev returns reverse(op).
 // For example, Brrev(<) is >.
-func Brrev(a int) int {
-	switch a {
+func Brrev(op Op) Op {
+	switch op {
 	case OEQ:
 		return OEQ
 	case ONE:
@@ -1845,8 +1845,8 @@
 	case OGE:
 		return OLE
 	}
-	Fatalf("brrev: no rev for %v\n", Oconv(a, 0))
-	return a
+	Fatalf("brrev: no rev for %v\n", Oconv(int(op), 0))
+	return op
 }
 
 // return side effect-free n, appending side effects to init.
@@ -2991,12 +2991,12 @@
 // even simpler simtype; get rid of ptr, bool.
 // assuming that the front end has rejected
 // all the invalid conversions (like ptr -> bool)
-func Simsimtype(t *Type) int {
+func Simsimtype(t *Type) EType {
 	if t == nil {
 		return 0
 	}
 
-	et := int(Simtype[t.Etype])
+	et := Simtype[t.Etype]
 	switch et {
 	case TPTR32:
 		et = TUINT32
diff --git a/src/cmd/compile/internal/gc/syntax.go b/src/cmd/compile/internal/gc/syntax.go
index 8748004..e48f692 100644
--- a/src/cmd/compile/internal/gc/syntax.go
+++ b/src/cmd/compile/internal/gc/syntax.go
@@ -42,11 +42,11 @@
 
 	Esc uint16 // EscXXX
 
-	Op          uint8
+	Op          Op
 	Nointerface bool
 	Ullman      uint8 // sethi/ullman number
 	Addable     bool  // addressable
-	Etype       uint8 // op for OASOP, etype for OTYPE, exclam for export, 6g saved reg
+	Etype       EType // op for OASOP, etype for OTYPE, exclam for export, 6g saved reg
 	Bounded     bool  // bounds check unnecessary
 	Class       Class // PPARAM, PAUTO, PEXTERN, etc
 	Embedded    uint8 // ODCLFIELD embedded type
@@ -179,9 +179,11 @@
 	Systemstack    bool // must run on system stack
 }
 
+type Op uint8
+
 // Node ops.
 const (
-	OXXX = iota
+	OXXX = Op(iota)
 
 	// names
 	ONAME    // var, const or func name
diff --git a/src/cmd/compile/internal/gc/typecheck.go b/src/cmd/compile/internal/gc/typecheck.go
index 1d9ad55..354a2fa 100644
--- a/src/cmd/compile/internal/gc/typecheck.go
+++ b/src/cmd/compile/internal/gc/typecheck.go
@@ -75,8 +75,8 @@
 	if Isslice(t) {
 		return "slice"
 	}
-	et := int(t.Etype)
-	if 0 <= et && et < len(_typekind) {
+	et := t.Etype
+	if int(et) < len(_typekind) {
 		s := _typekind[et]
 		if s != "" {
 			return s
@@ -410,7 +410,8 @@
 		}
 		t := typ(TCHAN)
 		t.Type = l.Type
-		t.Chan = n.Etype
+		// TODO(marvin): Fix Node.EType type union.
+		t.Chan = uint8(n.Etype)
 		n.Op = OTYPE
 		n.Type = t
 		n.Left = nil
@@ -503,7 +504,7 @@
 		OSUB,
 		OXOR:
 		var l *Node
-		var op int
+		var op Op
 		var r *Node
 		if n.Op == OASOP {
 			ok |= Etop
@@ -514,7 +515,8 @@
 				n.Type = nil
 				return
 			}
-			op = int(n.Etype)
+			// TODO(marvin): Fix Node.EType type union.
+			op = Op(n.Etype)
 		} else {
 			ok |= Erv
 			l = typecheck(&n.Left, Erv|top&Eiota)
@@ -523,7 +525,7 @@
 				n.Type = nil
 				return
 			}
-			op = int(n.Op)
+			op = n.Op
 		}
 		if op == OLSH || op == ORSH {
 			defaultlit(&r, Types[TUINT])
@@ -562,11 +564,11 @@
 		if t.Etype == TIDEAL {
 			t = r.Type
 		}
-		et := int(t.Etype)
+		et := t.Etype
 		if et == TIDEAL {
 			et = TINT
 		}
-		aop := 0
+		var aop Op = OXXX
 		if iscmp[n.Op] && t.Etype != TIDEAL && !Eqtype(l.Type, r.Type) {
 			// comparison is okay as long as one side is
 			// assignable to the other.  convert so they have
@@ -619,7 +621,7 @@
 			}
 
 		converted:
-			et = int(t.Etype)
+			et = t.Etype
 		}
 
 		if t.Etype != TIDEAL && !Eqtype(l.Type, r.Type) {
@@ -701,7 +703,8 @@
 
 		if et == TSTRING {
 			if iscmp[n.Op] {
-				n.Etype = n.Op
+				// TODO(marvin): Fix Node.EType type union.
+				n.Etype = EType(n.Op)
 				n.Op = OCMPSTR
 			} else if n.Op == OADD {
 				// create OADDSTR node with list of strings in x + y + z + (w + v) + ...
@@ -731,7 +734,8 @@
 			} else if r.Op == OLITERAL && r.Val().Ctype() == CTNIL {
 			} else // leave alone for back end
 			if Isinter(r.Type) == Isinter(l.Type) {
-				n.Etype = n.Op
+				// TODO(marvin): Fix Node.EType type union.
+				n.Etype = EType(n.Op)
 				n.Op = OCMPIFACE
 			}
 		}
@@ -1251,12 +1255,14 @@
 		n.Diag |= n.Left.Diag
 		l = n.Left
 		if l.Op == ONAME && l.Etype != 0 {
-			if n.Isddd && l.Etype != OAPPEND {
+			// TODO(marvin): Fix Node.EType type union.
+			if n.Isddd && Op(l.Etype) != OAPPEND {
 				Yyerror("invalid use of ... with builtin %v", l)
 			}
 
 			// builtin: OLEN, OCAP, etc.
-			n.Op = l.Etype
+			// TODO(marvin): Fix Node.EType type union.
+			n.Op = Op(l.Etype)
 
 			n.Left = n.Right
 			n.Right = nil
@@ -1408,7 +1414,7 @@
 				n.Orig = r
 			}
 
-			n.Type = Types[cplxsubtype(int(t.Etype))]
+			n.Type = Types[cplxsubtype(t.Etype)]
 			break OpSwitch
 		}
 
@@ -1733,8 +1739,8 @@
 			return
 		}
 		var why string
-		n.Op = uint8(convertop(t, n.Type, &why))
-		if (n.Op) == 0 {
+		n.Op = convertop(t, n.Type, &why)
+		if n.Op == 0 {
 			if n.Diag == 0 && !n.Type.Broke {
 				Yyerror("cannot convert %v to type %v%s", Nconv(n.Left, obj.FmtLong), n.Type, why)
 				n.Diag = 1
@@ -2442,7 +2448,7 @@
 }
 
 func derefall(t *Type) *Type {
-	for t != nil && int(t.Etype) == Tptr {
+	for t != nil && t.Etype == Tptr {
 		t = t.Type
 	}
 	return t
@@ -2514,20 +2520,20 @@
 		dowidth(tt)
 		rcvr := getthisx(f2.Type).Type.Type
 		if !Eqtype(rcvr, tt) {
-			if int(rcvr.Etype) == Tptr && Eqtype(rcvr.Type, tt) {
+			if rcvr.Etype == Tptr && Eqtype(rcvr.Type, tt) {
 				checklvalue(n.Left, "call pointer method on")
 				n.Left = Nod(OADDR, n.Left, nil)
 				n.Left.Implicit = true
 				typecheck(&n.Left, Etype|Erv)
-			} else if int(tt.Etype) == Tptr && int(rcvr.Etype) != Tptr && Eqtype(tt.Type, rcvr) {
+			} else if tt.Etype == Tptr && rcvr.Etype != Tptr && Eqtype(tt.Type, rcvr) {
 				n.Left = Nod(OIND, n.Left, nil)
 				n.Left.Implicit = true
 				typecheck(&n.Left, Etype|Erv)
-			} else if int(tt.Etype) == Tptr && int(tt.Type.Etype) == Tptr && Eqtype(derefall(tt), derefall(rcvr)) {
+			} else if tt.Etype == Tptr && tt.Type.Etype == Tptr && Eqtype(derefall(tt), derefall(rcvr)) {
 				Yyerror("calling method %v with receiver %v requires explicit dereference", n.Right, Nconv(n.Left, obj.FmtLong))
-				for int(tt.Etype) == Tptr {
+				for tt.Etype == Tptr {
 					// Stop one level early for method with pointer receiver.
-					if int(rcvr.Etype) == Tptr && int(tt.Type.Etype) != Tptr {
+					if rcvr.Etype == Tptr && tt.Type.Etype != Tptr {
 						break
 					}
 					n.Left = Nod(OIND, n.Left, nil)
@@ -2597,7 +2603,7 @@
 }
 
 // typecheck assignment: type list = expression list
-func typecheckaste(op int, call *Node, isddd bool, tstruct *Type, nl *NodeList, desc func() string) {
+func typecheckaste(op Op, call *Node, isddd bool, tstruct *Type, nl *NodeList, desc func() string) {
 	var t *Type
 	var n *Node
 	var n1 int
@@ -2915,7 +2921,7 @@
 	}
 
 	// Save original node (including n->right)
-	norig := Nod(int(n.Op), nil, nil)
+	norig := Nod(n.Op, nil, nil)
 
 	*norig = *n
 
diff --git a/src/cmd/compile/internal/gc/walk.go b/src/cmd/compile/internal/gc/walk.go
index 875b7ab..a2bdbdc 100644
--- a/src/cmd/compile/internal/gc/walk.go
+++ b/src/cmd/compile/internal/gc/walk.go
@@ -313,19 +313,19 @@
 				if f.Op != OCALLFUNC && f.Op != OCALLMETH && f.Op != OCALLINTER {
 					Fatalf("expected return of call, have %v", f)
 				}
-				n.List = concat(list1(f), ascompatet(int(n.Op), rl, &f.Type, 0, &n.Ninit))
+				n.List = concat(list1(f), ascompatet(n.Op, rl, &f.Type, 0, &n.Ninit))
 				break
 			}
 
 			// move function calls out, to make reorder3's job easier.
 			walkexprlistsafe(n.List, &n.Ninit)
 
-			ll := ascompatee(int(n.Op), rl, n.List, &n.Ninit)
+			ll := ascompatee(n.Op, rl, n.List, &n.Ninit)
 			n.List = reorder3(ll)
 			break
 		}
 
-		ll := ascompatte(int(n.Op), nil, false, Getoutarg(Curfn.Type), n.List, 1, &n.Ninit)
+		ll := ascompatte(n.Op, nil, false, Getoutarg(Curfn.Type), n.List, 1, &n.Ninit)
 		n.List = ll
 
 	case ORETJMP:
@@ -579,7 +579,7 @@
 		}
 		walkexpr(&n.Left, init)
 		walkexprlist(n.List, init)
-		ll := ascompatte(int(n.Op), n, n.Isddd, getinarg(t), n.List, 0, init)
+		ll := ascompatte(n.Op, n, n.Isddd, getinarg(t), n.List, 0, init)
 		n.List = reorder1(ll)
 
 	case OCALLFUNC:
@@ -626,7 +626,7 @@
 			}
 		}
 
-		ll := ascompatte(int(n.Op), n, n.Isddd, getinarg(t), n.List, 0, init)
+		ll := ascompatte(n.Op, n, n.Isddd, getinarg(t), n.List, 0, init)
 		n.List = reorder1(ll)
 
 	case OCALLMETH:
@@ -636,8 +636,8 @@
 		}
 		walkexpr(&n.Left, init)
 		walkexprlist(n.List, init)
-		ll := ascompatte(int(n.Op), n, false, getthis(t), list1(n.Left.Left), 0, init)
-		lr := ascompatte(int(n.Op), n, n.Isddd, getinarg(t), n.List, 0, init)
+		ll := ascompatte(n.Op, n, false, getthis(t), list1(n.Left.Left), 0, init)
+		lr := ascompatte(n.Op, n, n.Isddd, getinarg(t), n.List, 0, init)
 		ll = concat(ll, lr)
 		n.Left.Left = nil
 		ullmancalc(n.Left)
@@ -748,7 +748,7 @@
 		walkexprlistsafe(n.List, init)
 		walkexpr(&r, init)
 
-		ll := ascompatet(int(n.Op), n.List, &r.Type, 0, init)
+		ll := ascompatet(n.Op, n.List, &r.Type, 0, init)
 		for lr := ll; lr != nil; lr = lr.Next {
 			lr.N = applywritebarrier(lr.N, init)
 		}
@@ -1103,7 +1103,7 @@
 		walkexpr(&n.Right, init)
 
 		// rewrite complex div into function call.
-		et := int(n.Left.Type.Etype)
+		et := n.Left.Type.Etype
 
 		if Iscomplex[et] && n.Op == ODIV {
 			t := n.Type
@@ -1291,7 +1291,8 @@
 	// without the function call.
 	case OCMPSTR:
 		if (Isconst(n.Left, CTSTR) && len(n.Left.Val().U.(string)) == 0) || (Isconst(n.Right, CTSTR) && len(n.Right.Val().U.(string)) == 0) {
-			r := Nod(int(n.Etype), Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil))
+			// TODO(marvin): Fix Node.EType type union.
+			r := Nod(Op(n.Etype), Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil))
 			typecheck(&r, Erv)
 			walkexpr(&r, init)
 			r.Type = n.Type
@@ -1300,8 +1301,9 @@
 		}
 
 		// s + "badgerbadgerbadger" == "badgerbadgerbadger"
-		if (n.Etype == OEQ || n.Etype == ONE) && Isconst(n.Right, CTSTR) && n.Left.Op == OADDSTR && count(n.Left.List) == 2 && Isconst(n.Left.List.Next.N, CTSTR) && strlit(n.Right) == strlit(n.Left.List.Next.N) {
-			r := Nod(int(n.Etype), Nod(OLEN, n.Left.List.N, nil), Nodintconst(0))
+		if (Op(n.Etype) == OEQ || Op(n.Etype) == ONE) && Isconst(n.Right, CTSTR) && n.Left.Op == OADDSTR && count(n.Left.List) == 2 && Isconst(n.Left.List.Next.N, CTSTR) && strlit(n.Right) == strlit(n.Left.List.Next.N) {
+			// TODO(marvin): Fix Node.EType type union.
+			r := Nod(Op(n.Etype), Nod(OLEN, n.Left.List.N, nil), Nodintconst(0))
 			typecheck(&r, Erv)
 			walkexpr(&r, init)
 			r.Type = n.Type
@@ -1310,7 +1312,8 @@
 		}
 
 		var r *Node
-		if n.Etype == OEQ || n.Etype == ONE {
+		// TODO(marvin): Fix Node.EType type union.
+		if Op(n.Etype) == OEQ || Op(n.Etype) == ONE {
 			// prepare for rewrite below
 			n.Left = cheapexpr(n.Left, init)
 
@@ -1320,7 +1323,8 @@
 
 			// quick check of len before full compare for == or !=
 			// eqstring assumes that the lengths are equal
-			if n.Etype == OEQ {
+			// TODO(marvin): Fix Node.EType type union.
+			if Op(n.Etype) == OEQ {
 				// len(left) == len(right) && eqstring(left, right)
 				r = Nod(OANDAND, Nod(OEQ, Nod(OLEN, n.Left, nil), Nod(OLEN, n.Right, nil)), r)
 			} else {
@@ -1336,7 +1340,8 @@
 			// sys_cmpstring(s1, s2) :: 0
 			r = mkcall("cmpstring", Types[TINT], init, conv(n.Left, Types[TSTRING]), conv(n.Right, Types[TSTRING]))
 
-			r = Nod(int(n.Etype), r, Nodintconst(0))
+			// TODO(marvin): Fix Node.EType type union.
+			r = Nod(Op(n.Etype), r, Nodintconst(0))
 		}
 
 		typecheck(&r, Erv)
@@ -1514,12 +1519,14 @@
 		n.Left = cheapexpr(n.Left, init)
 		substArgTypes(fn, n.Right.Type, n.Left.Type)
 		r := mkcall1(fn, n.Type, init, n.Left, n.Right)
-		if n.Etype == ONE {
+		// TODO(marvin): Fix Node.EType type union.
+		if Op(n.Etype) == ONE {
 			r = Nod(ONOT, r, nil)
 		}
 
 		// check itable/type before full compare.
-		if n.Etype == OEQ {
+		// TODO(marvin): Fix Node.EType type union.
+		if Op(n.Etype) == OEQ {
 			r = Nod(OANDAND, Nod(OEQ, Nod(OITAB, n.Left, nil), Nod(OITAB, n.Right, nil)), r)
 		} else {
 			r = Nod(OOROR, Nod(ONE, Nod(OITAB, n.Left, nil), Nod(OITAB, n.Right, nil)), r)
@@ -1587,7 +1594,7 @@
 	return n
 }
 
-func ascompatee1(op int, l *Node, r *Node, init **NodeList) *Node {
+func ascompatee1(op Op, l *Node, r *Node, init **NodeList) *Node {
 	// convas will turn map assigns into function calls,
 	// making it impossible for reorder3 to work.
 	n := Nod(OAS, l, r)
@@ -1599,7 +1606,7 @@
 	return convas(n, init)
 }
 
-func ascompatee(op int, nl *NodeList, nr *NodeList, init **NodeList) *NodeList {
+func ascompatee(op Op, nl *NodeList, nr *NodeList, init **NodeList) *NodeList {
 	// check assign expression list to
 	// a expression list. called in
 	//	expr-list = expr-list
@@ -1648,7 +1655,7 @@
 	return true
 }
 
-func ascompatet(op int, nl *NodeList, nr **Type, fp int, init **NodeList) *NodeList {
+func ascompatet(op Op, nl *NodeList, nr **Type, fp int, init **NodeList) *NodeList {
 	var l *Node
 	var tmp *Node
 	var a *Node
@@ -1789,7 +1796,7 @@
 // a type list. called in
 //	return expr-list
 //	func(expr-list)
-func ascompatte(op int, call *Node, isddd bool, nl **Type, lr *NodeList, fp int, init **NodeList) *NodeList {
+func ascompatte(op Op, call *Node, isddd bool, nl **Type, lr *NodeList, fp int, init **NodeList) *NodeList {
 	var savel Iter
 
 	lr0 := lr
@@ -1902,9 +1909,9 @@
 	var n *Node
 	var on *Node
 	var t *Type
-	var et int
+	var et EType
 
-	op := int(nn.Op)
+	op := nn.Op
 	all := nn.List
 	var calls *NodeList
 	notfirst := false
@@ -1945,7 +1952,7 @@
 		}
 
 		t = n.Type
-		et = int(n.Type.Etype)
+		et = n.Type.Etype
 		if Isinter(n.Type) {
 			if isnilinter(n.Type) {
 				on = syslook("printeface", 1)
@@ -3162,7 +3169,7 @@
 	typecheck(&a, Etop)
 	*init = list(*init, a)
 
-	andor := OANDAND
+	var andor Op = OANDAND
 	if n.Op == ONE {
 		andor = OOROR
 	}
@@ -3176,7 +3183,7 @@
 		for i := 0; int64(i) < t.Bound; i++ {
 			li = Nod(OINDEX, l, Nodintconst(int64(i)))
 			ri = Nod(OINDEX, r, Nodintconst(int64(i)))
-			a = Nod(int(n.Op), li, ri)
+			a = Nod(n.Op, li, ri)
 			if expr == nil {
 				expr = a
 			} else {
@@ -3202,7 +3209,7 @@
 			}
 			li = Nod(OXDOT, l, newname(t1.Sym))
 			ri = Nod(OXDOT, r, newname(t1.Sym))
-			a = Nod(int(n.Op), li, ri)
+			a = Nod(n.Op, li, ri)
 			if expr == nil {
 				expr = a
 			} else {
@@ -3917,7 +3924,7 @@
 	Curfn = nil
 	funchdr(fn)
 
-	a = Nod(int(n.Op), nil, nil)
+	a = Nod(n.Op, nil, nil)
 	a.List = printargs
 	typecheck(&a, Etop)
 	walkstmt(&a)
diff --git a/src/cmd/compile/internal/gc/y.go b/src/cmd/compile/internal/gc/y.go
index 7e6ae02..2bc3e40 100644
--- a/src/cmd/compile/internal/gc/y.go
+++ b/src/cmd/compile/internal/gc/y.go
@@ -1560,7 +1560,7 @@
 		//line go.y:489
 		{
 			yyVAL.node = Nod(OASOP, yyDollar[1].node, yyDollar[3].node)
-			yyVAL.node.Etype = uint8(yyDollar[2].i) // rathole to pass opcode
+			yyVAL.node.Etype = EType(yyDollar[2].i) // rathole to pass opcode
 		}
 	case 51:
 		yyDollar = yyS[yypt-3 : yypt+1]
@@ -1602,7 +1602,7 @@
 		{
 			yyVAL.node = Nod(OASOP, yyDollar[1].node, Nodintconst(1))
 			yyVAL.node.Implicit = true
-			yyVAL.node.Etype = OADD
+			yyVAL.node.Etype = EType(OADD)
 		}
 	case 54:
 		yyDollar = yyS[yypt-2 : yypt+1]
@@ -1610,7 +1610,7 @@
 		{
 			yyVAL.node = Nod(OASOP, yyDollar[1].node, Nodintconst(1))
 			yyVAL.node.Implicit = true
-			yyVAL.node.Etype = OSUB
+			yyVAL.node.Etype = EType(OSUB)
 		}
 	case 55:
 		yyDollar = yyS[yypt-3 : yypt+1]