Commits

Joseph Poirier  committed a07aa58 Merge

Merged changes from golang.

  • Participants
  • Parent commits 1de7a4c, 0a0a751

Comments (0)

Files changed (255)

 920e9d1ffd1f46665dd152aa9cf3c0f17d68dd88 go1
 2ccfd4b451d319941bfe3e08037e1462d3c15093 go1.0.1
 5e806355a9e1491aaab53d3612fed4c550b130c0 go1.0.2
-5e806355a9e1491aaab53d3612fed4c550b130c0 release
+2d8bc3c94ecb3ec8f70556d5fd237788903c7281 go1.0.3
+2d8bc3c94ecb3ec8f70556d5fd237788903c7281 release
 Jongmin Kim <atomaths@gmail.com>
 Jose Luis Vázquez González <josvazg@gmail.com>
 Josh Goebel <dreamer3@gmail.com>
+Josh Holland <jrh@joshh.co.uk>
 Jukka-Pekka Kekkonen <karatepekka@gmail.com>
 Julian Phillips <julian@quantumfyre.co.uk>
 Julien Schmidt <google@julienschmidt.com>
 Sergio Luis O. B. Correia <sergio@larces.uece.br>
 Shawn Smith <shawn.p.smith@gmail.com>
 Shenghou Ma <minux.ma@gmail.com>
+Shivakumar GN <shivakumar.gn@gmail.com>
 Spring Mc <heresy.mc@gmail.com>
 Stefan Nilsson <snilsson@nada.kth.se> <trolleriprofessorn@gmail.com>
 Stéphane Travostino <stephane.travostino@gmail.com>

File CONTRIBUTORS

 John Beisley <huin@google.com>
 John DeNero <denero@google.com>
 Jonathan Allie <jonallie@google.com>
+Jonathan Feinberg <feinberg@google.com>
 Jonathan Gold <jgold.bg@gmail.com>
 Jonathan Mark <jhmark@xenops.com> <jhmark000@gmail.com>
 Jonathan Pittman <jmpittman@google.com> <jonathan.mark.pittman@gmail.com>
 Jos Visser <josv@google.com>
 Jose Luis Vázquez González <josvazg@gmail.com>
 Josh Goebel <dreamer3@gmail.com>
+Josh Holland <jrh@joshh.co.uk>
 Jukka-Pekka Kekkonen <karatepekka@gmail.com>
 Julian Phillips <julian@quantumfyre.co.uk>
 Julien Schmidt <google@julienschmidt.com>
 Sergio Luis O. B. Correia <sergio@larces.uece.br>
 Shawn Smith <shawn.p.smith@gmail.com>
 Shenghou Ma <minux.ma@gmail.com>
+Shivakumar GN <shivakumar.gn@gmail.com>
 Spring Mc <heresy.mc@gmail.com>
 Stefan Nilsson <snilsson@nada.kth.se> <trolleriprofessorn@gmail.com>
 Stéphane Travostino <stephane.travostino@gmail.com>

File VERSION

-weekly.2012-01-27 11727+11826+

File doc/contrib.html

 <h3 id="release"><a href="/doc/devel/release.html">Release History</a></h3>
 <p>A summary of the changes between Go releases.</p>
 
-<h3 id="weekly"><a href="/doc/devel/weekly.html">Weekly Snapshot History</a></h3>
-<p>A summary of the changes between weekly snapshots of Go.</p>
-
 <h3 id="golang-dev"><a href="http://groups.google.com/group/golang-dev">Developer Mailing List</a></h3>
 <p>The <a href="http://groups.google.com/group/golang-dev">golang-dev</a>
 mailing list is for discussing and reviewing code for the Go project.</p>

File doc/contribute.html

 <p>
 This document explains how to contribute changes to the Go project.
 It assumes you have installed Go using the
-<a href="/doc/install">installation instructions</a> and
+<a href="/doc/install/source">installation instructions</a> and
 have <a href="code.html">written and tested your code</a>.
 (Note that the <code>gccgo</code> frontend lives elsewhere;
 see <a href="gccgo_contribute.html">Contributing to gccgo</a>.)

File doc/devel/release.html

 }-->
 
 <p>This page summarizes the changes between official stable releases of Go.
-Between releases we issue less stable
-<a href="http://blog.golang.org/2011/03/go-becomes-more-stable.html">weekly snapshots</a>.
-The <a href="weekly.html">weekly snapshot history</a> contains more detail,
-and the <a href="http://code.google.com/p/go/source/list">Mercurial change log</a>
-has full details.</p>
+The <a href="http://code.google.com/p/go/source/list">Mercurial change log</a>
+has the full details.</p>
 
 <p>To update to a specific release, use:</p>
 

File doc/effective_go.html

         log.Fatal("$USER not set")
     }
     if HOME == "" {
-        HOME = "/usr/" + USER
+        HOME = "/home/" + USER
     }
     if GOROOT == "" {
         GOROOT = HOME + "/go"

File doc/go1.1.html

+<!--{
+	"Title": "Go 1.1 Release Notes",
+	"Path":  "/doc/go1.1",
+	"Template": true
+}-->
+
+<h2 id="introduction">Introduction to Go 1.1</h2>
+
+TODO
+ - overview
+ - link back to Go 1 and also Go 1 Compatibility docs.
+
+<h2 id="language">Changes to the language</h2>
+
+TODO
+
+<h2 id="impl">Changes to the implementations and tools</h2>
+
+TODO: more
+
+<h3 id="int">Size of int on 64-bit platforms</h3>
+
+<p>
+The language allows the implementation to choose whether the <code>int</code> type and <code>uint</code> types are 32 or 64 bits. Previous Go implementations made <code>int</code> and <code>uint</code> 32 bits on all systems. Both the gc and gccgo implementations (TODO: check that gccgo does) <a href="http://golang.org/issue/2188">now make <code>int</code> and <code>uint</code> 64 bits on 64-bit platforms such as AMD64/x86-64</a>.
+Among other things, this enables the allocation of slices with
+more than 2 billion elements on 64-bit platforms.
+</p>
+
+<p>
+<em>Updating</em>:
+Most programs will be unaffected by this change.
+Because Go does not allow implicit conversions between distinct
+<a href="/ref/spec#Numeric_types">numeric types</a>,
+no programs will stop compiling due to this change.
+However, programs that contain implicit assumptions
+that <code>int</code> is only 32 bits may change behavior.
+For example, this code prints a positive number on 64-bit systems and
+a negative one on 32-bit systems:
+
+<pre>
+x := ^uint32(0) // x is 0xffffffff
+i := int(x)     // i is -1 on 32-bit systems, 0xffffffff on 64-bit
+fmt.Println(i)
+</pre>
+
+<p>Portable code intending 32-bit sign extension (yielding -1 on all systems)
+would instead say:
+</p>
+
+<pre>
+i := int(int32(x))
+</pre>
+
+<h3 id="asm">Assembler</h3>
+
+<p>
+Due to the <a href="#int">int</a> and TODO: OTHER changes,
+the placement of function arguments on the stack has changed.
+Functions written in assembly will need to be revised at least
+to adjust frame pointer offsets.
+</p>
+
+<h2 id="library">Changes to the standard library</h2>
+
+TODO

File doc/go_faq.html

 <!--{
-	"Title": "FAQ"
+	"Title": "FAQ",
+	"Path": "/doc/faq"
 }-->
 
 <h2 id="Origins">Origins</h2>
 <p>
 The sizes of <code>int</code> and <code>uint</code> are implementation-specific
 but the same as each other on a given platform.
-The 64 bit Go compilers (both gc and gccgo) use a 32 bit representation for
-<code>int</code>.  Code that relies on a particular
+For portability, code that relies on a particular
 size of value should use an explicitly sized type, like <code>int64</code>.
+Prior to Go 1.1, the 64-bit Go compilers (both gc and gccgo) used
+a 32-bit representation for <code>int</code>. As of Go 1.1 they use
+a 64-bit representation.
 On the other hand, floating-point scalars and complex
 numbers are always sized: <code>float32</code>, <code>complex64</code>,
 etc., because programmers should be aware of precision when using

File doc/go_spec.html

 <!--{
 	"Title": "The Go Programming Language Specification",
-	"Subtitle": "Version of September 22, 2012",
+	"Subtitle": "Version of September 26, 2012",
 	"Path": "/ref/spec"
 }-->
 
 </p>
 
 <pre class="ebnf">
-Conversion = Type "(" Expression ")" .
+Conversion = Type "(" Expression [ "," ] ")" .
 </pre>
 
 <p>
 	<code>x</code>'s type and <code>T</code> are both complex types.
 	</li>
 	<li>
-	<code>x</code> is an integer or has type <code>[]byte</code> or
-	<code>[]rune</code> and <code>T</code> is a string type.
+	<code>x</code> is an integer or a slice of bytes or runes
+	and <code>T</code> is a string type.
 	</li>
 	<li>
-	<code>x</code> is a string and <code>T</code> is <code>[]byte</code> or
-	<code>[]rune</code>.
+	<code>x</code> is a string and <code>T</code> is a slice of bytes or runes.
 	</li>
 </ul>
 

File doc/install-source.html

 $ hg clone -u release https://code.google.com/p/go
 </pre>
 
+<h2 id="head">(Optional) Switch to the default branch</h2>
+
+<p>If you intend to modify the go source code, and
+<a href="/doc/contribute.html">contribute your changes</a>
+to the project, then move your repository
+off the release branch, and onto the default (development) branch.
+Otherwise, skip this step.</p>
+
+<pre>
+$ hg update default
+</pre>
+
 <h2 id="install">Install Go</h2>
 
 <p>

File doc/install.html

 </pre>
 
 <p>
-Extract <a href="http://code.google.com/p/go/downloads/list?q=OpSys-FreeBSD+OR+OpSys-Linux+OR+OpSys-OSX+AND+Type-Archive">the archive</a>
-into <code>/usr/local</code>, creating a Go tree in <code>/usr/local/go</code>:
+Extract <a href="http://code.google.com/p/go/downloads/list?q=OpSys-FreeBSD+OR+OpSys-Linux+OR+OpSys-OSX+Type-Archive">the archive</a>
+into <code>/usr/local</code>, creating a Go tree in <code>/usr/local/go</code>.
+For example:
 </p>
 
 <pre>
-tar -C /usr/local -xzf go1.0.2.linux-amd64.tar.gz
+tar -C /usr/local -xzf go1.0.3.linux-amd64.tar.gz
 </pre>
 
 <p>
+The name of the archive may differ, depending on the version of Go you are
+installing and your system's operating system and processor architecture.
+</p>
+
+<p>
 (Typically these commands must be run as root or through <code>sudo</code>.)
 </p>
 
 <h3 id="osx">Mac OS X package installer</h3>
 
 <p>
-Open the <a href="http://code.google.com/p/go/downloads/list?q=OpSys-Darwin+AND+Type-Installer">package file</a>
+Open the <a href="http://code.google.com/p/go/downloads/list?q=OpSys-OSX+Type-Installer">package file</a>
 and follow the prompts to install the Go tools.
 The package installs the Go distribution to <code>/usr/local/go</code>.
 </p>

File lib/codereview/codereview.py

 		cmd = ["gofmt", "-l"]
 		if not opts["list"]:
 			cmd += ["-w"]
-		if os.spawnvp(os.P_WAIT, "gofmt", cmd + files) != 0:
+		if subprocess.call(cmd + files) != 0:
 			raise hg_util.Abort("gofmt did not exit cleanly")
 	except hg_error.Abort, e:
 		raise

File misc/cgo/life/life.go

 
 import "unsafe"
 
-func Run(gen, x, y int, a []int) {
-	n := make([]int, x*y)
+func Run(gen, x, y int, a []int32) {
+	n := make([]int32, x*y)
 	for i := 0; i < gen; i++ {
 		C.Step(C.int(x), C.int(y), (*C.int)(unsafe.Pointer(&a[0])), (*C.int)(unsafe.Pointer(&n[0])))
 		copy(a, n)

File misc/cgo/life/main.go

 func main() {
 	flag.Parse()
 
-	var a [MAXDIM * MAXDIM]int
+	var a [MAXDIM * MAXDIM]int32
 	for i := 2; i < *dim; i += 8 {
 		for j := 2; j < *dim-3; j += 8 {
 			for y := 0; y < 3; y++ {

File misc/cgo/test/issue1560.go

 }
 
 //export BackgroundSleep
-func BackgroundSleep(n int) {
+func BackgroundSleep(n int32) {
 	go func() {
 		C.sleep(C.uint(n))
 		sleepDone <- true

File src/cmd/5c/txt.c

 void
 gpseudo(int a, Sym *s, Node *n)
 {
-
 	nextpc();
 	p->as = a;
 	p->from.type = D_OREG;
 	p->from.sym = s;
 	p->from.name = D_EXTERN;
-	if(a == ATEXT) {
+	if(a == ATEXT || a == AGLOBL) {
 		p->reg = textflag;
 		textflag = 0;
-	} else if(a == AGLOBL)
-		p->reg = 0;
+	}
 	if(s->class == CSTATIC)
 		p->from.name = D_STATIC;
 	naddr(n, &p->to);

File src/cmd/5g/cgen.c

 	while(n->op == OCONVNOP)
 		n = n->left;
 
+	if(isconst(n, CTNIL) && n->type->width > widthptr) {
+		// Use of a nil interface or nil slice.
+		// Create a temporary we can take the address of and read.
+		// The generated code is just going to panic, so it need not
+		// be terribly efficient. See issue 3670.
+		tempname(&n1, n->type);
+		clearfat(&n1);
+		regalloc(&n2, types[tptr], res);
+		gins(AMOVW, &n1, &n2);
+		gmove(&n2, res);
+		regfree(&n2);
+		goto ret;
+	}
+		
+
 	if(n->addable) {
 		memset(&n1, 0, sizeof n1);
 		n1.op = OADDR;

File src/cmd/5g/galign.c

 betypeinit(void)
 {
 	widthptr = 4;
+	widthint = 4;
 
 	zprog.link = P;
 	zprog.as = AGOK;

File src/cmd/5g/gg.h

 void	proglist(void);
 Prog*	gbranch(int, Type*, int);
 Prog*	prog(int);
-void	gaddoffset(Node*);
 void	gconv(int, int);
 int	conv2pt(Type*);
 vlong	convvtox(vlong, int);
 void	fnparam(Type*, int, int);
 Prog*	gop(int, Node*, Node*, Node*);
-void	setconst(Addr*, vlong);
-void	setaddr(Addr*, Node*);
 int	optoas(int, Type*);
 void	ginit(void);
 void	gclean(void);

File src/cmd/5g/opt.h

 #define	D_HI	D_NONE
 #define	D_LO	D_NONE
 
-#define	isregtype(t)	((t)>= D_AX && (t)<=D_R15)
-
 #define	BLOAD(r)	band(bnot(r->refbehind), r->refahead)
 #define	BSTORE(r)	band(bnot(r->calbehind), r->calahead)
 #define	LOAD(r)		(~r->refbehind.b[z] & r->refahead.b[z])
 typedef	struct	Reg	Reg;
 typedef	struct	Rgn	Rgn;
 
+// A Reg is a wrapper around a single Prog (one instruction) that holds
+// register optimization information while the optimizer runs.
+// r->prog is the instruction.
+// r->prog->regp points back to r.
 struct	Reg
 {
 
-	Bits	set;
-	Bits	use1;
-	Bits	use2;
+	Bits	set;  		// variables written by this instruction.
+	Bits	use1; 		// variables read by prog->from.
+	Bits	use2; 		// variables read by prog->to.
 
 	Bits	refbehind;
 	Bits	refahead;
 	uint16	loop;		// x5 for every loop
 	uchar	refset;		// diagnostic generated
 
-	Reg*	p1;
-	Reg*	p2;
+	Reg*	p1;     	// predecessors of this instruction: p1,
+	Reg*	p2;     	// and then p2 linked though p2link.
 	Reg*	p2link;
-	Reg*	s1;
+	Reg*	s1;     	// successors of this instruction (at most two: s1 and s2).
 	Reg*	s2;
-	Reg*	link;
-	Prog*	prog;
+	Reg*	link;   	// next instruction in function code
+	Prog*	prog;   	// actual instruction
 };
 #define	R	((Reg*)0)
 

File src/cmd/5g/reg.c

 	v->node = node;
 	
 	if(debug['R'])
-		print("bit=%2d et=%2d w=%d+%d %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
+		print("bit=%2d et=%2E w=%d+%d %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
 
 	bit = blsh(i);
 	if(n == D_EXTERN || n == D_STATIC)

File src/cmd/5l/l.h

 {
 	thechar = '5',
 	PtrSize = 4,
+	IntSize = 4,
 	FuncAlign = 4  // single-instruction alignment
 };
 

File src/cmd/6a/lex.c

 	"PREFETCHT2",		LTYPE2,	APREFETCHT2,
 	"PREFETCHNTA",		LTYPE2,	APREFETCHNTA,
 	"UNDEF",	LTYPE0,	AUNDEF,
+	"AESENC",	LTYPE3,	AAESENC,
+	"AESENCLAST",	LTYPE3, AAESENCLAST,
+	"AESDEC",	LTYPE3, AAESDEC,
+	"AESDECLAST",	LTYPE3, AAESDECLAST,
+	"AESIMC",	LTYPE3, AAESIMC,
+	"AESKEYGENASSIST", LTYPEX, AAESKEYGENASSIST,
+	"PSHUFD", LTYPEX, APSHUFD,
 
 	0
 };

File src/cmd/6c/gc.h

 #define	D_HI	D_NONE
 #define	D_LO	D_NONE
 
-#define	isregtype(t)	((t)>= D_AX && (t)<=D_R15)
-
 /*
  * bound
  */

File src/cmd/6g/cgen.c

 	case OADD:
 	case OMUL:
 		a = optoas(n->op, nl->type);
-		if(a != AIMULB)
-			goto sbop;
-		cgen_bmul(n->op, nl, nr, res);
-		break;
+		if(a == AIMULB) {
+			cgen_bmul(n->op, nl, nr, res);
+			break;
+		}
+		goto sbop;
 
 	// asymmetric binary
 	case OSUB:
 
 	case OLEN:
 		if(istype(nl->type, TMAP) || istype(nl->type, TCHAN)) {
-			// map and chan have len in the first 32-bit word.
+			// map and chan have len in the first int-sized word.
 			// a zero pointer means zero length
 			regalloc(&n1, types[tptr], res);
 			cgen(nl, &n1);
 
 			n2 = n1;
 			n2.op = OINDREG;
-			n2.type = types[TINT32];
+			n2.type = types[simtype[TINT]];
 			gmove(&n2, &n1);
 
 			patch(p1, pc);
 			// both slice and string have len one pointer into the struct.
 			// a zero pointer means zero length
 			igen(nl, &n1, res);
-			n1.type = types[TUINT32];
+			n1.type = types[simtype[TUINT]];
 			n1.xoffset += Array_nel;
 			gmove(&n1, res);
 			regfree(&n1);
 
 	case OCAP:
 		if(istype(nl->type, TCHAN)) {
-			// chan has cap in the second 32-bit word.
+			// chan has cap in the second int-sized word.
 			// a zero pointer means zero length
 			regalloc(&n1, types[tptr], res);
 			cgen(nl, &n1);
 
 			n2 = n1;
 			n2.op = OINDREG;
-			n2.xoffset = 4;
-			n2.type = types[TINT32];
+			n2.xoffset = widthint;
+			n2.type = types[simtype[TINT]];
 			gmove(&n2, &n1);
 
 			patch(p1, pc);
 		}
 		if(isslice(nl->type)) {
 			igen(nl, &n1, res);
-			n1.type = types[TUINT32];
+			n1.type = types[simtype[TUINT]];
 			n1.xoffset += Array_cap;
 			gmove(&n1, res);
 			regfree(&n1);
 	while(n->op == OCONVNOP)
 		n = n->left;
 
+	if(isconst(n, CTNIL) && n->type->width > widthptr) {
+		// Use of a nil interface or nil slice.
+		// Create a temporary we can take the address of and read.
+		// The generated code is just going to panic, so it need not
+		// be terribly efficient. See issue 3670.
+		tempname(&n1, n->type);
+		clearfat(&n1);
+		regalloc(&n2, types[tptr], res);
+		gins(ALEAQ, &n1, &n2);
+		gmove(&n2, res);
+		regfree(&n2);
+		goto ret;
+	}
+		
 	if(n->addable) {
 		regalloc(&n1, types[tptr], res);
 		gins(ALEAQ, n, &n1);
 					nlen.type = types[tptr];
 					nlen.xoffset += Array_array;
 					gmove(&nlen, &n3);
-					nlen.type = types[TUINT32];
+					nlen.type = types[simtype[TUINT]];
 					nlen.xoffset += Array_nel-Array_array;
 				}
 			}
 				nlen.type = types[tptr];
 				nlen.xoffset += Array_array;
 				gmove(&nlen, &n3);
-				nlen.type = types[TUINT32];
+				nlen.type = types[simtype[TUINT]];
 				nlen.xoffset += Array_nel-Array_array;
 			}
 		}
 			v = mpgetfix(nr->val.u.xval);
 			if(isslice(nl->type) || nl->type->etype == TSTRING) {
 				if(!debug['B'] && !n->bounded) {
-					nodconst(&n2, types[TUINT32], v);
-					gins(optoas(OCMP, types[TUINT32]), &nlen, &n2);
-					p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
+					nodconst(&n2, types[simtype[TUINT]], v);
+					gins(optoas(OCMP, types[simtype[TUINT]]), &nlen, &n2);
+					p1 = gbranch(optoas(OGT, types[simtype[TUINT]]), T, +1);
 					ginscall(panicindex, -1);
 					patch(p1, pc);
 				}
 
 		if(!debug['B'] && !n->bounded) {
 			// check bounds
-			t = types[TUINT32];
+			t = types[simtype[TUINT]];
 			if(is64(nr->type))
 				t = types[TUINT64];
 			if(isconst(nl, CTSTR)) {
 	Type *fp;
 	Iter flist;
 	Node n1, n2;
- 
+
 	switch(n->op) {
 	case ONAME:
 		if((n->class&PHEAP) || n->class == PPARAMREF)
 		*a = *n;
 		return;
 
+	case OINDREG:
+		// Increase the refcount of the register so that igen's caller
+		// has to call regfree.
+		if(n->val.u.reg != D_SP)
+			reg[n->val.u.reg]++;
+		*a = *n;
+		return;
+
+	case ODOT:
+		igen(n->left, a, res);
+		a->xoffset += n->xoffset;
+		a->type = n->type;
+		return;
+
+	case ODOTPTR:
+		regalloc(a, types[tptr], res);
+		cgen(n->left, a);
+		if(n->xoffset != 0) {
+			// explicit check for nil if struct is large enough
+			// that we might derive too big a pointer.
+			if(n->left->type->type->width >= unmappedzero) {
+				n1 = *a;
+				n1.op = OINDREG;
+				n1.type = types[TUINT8];
+				n1.xoffset = 0;
+				gins(ATESTB, nodintconst(0), &n1);
+			}
+		}
+		a->op = OINDREG;
+		a->xoffset += n->xoffset;
+		a->type = n->type;
+		return;
+
 	case OCALLFUNC:
+	case OCALLMETH:
+	case OCALLINTER:
+		switch(n->op) {
+		case OCALLFUNC:
+			cgen_call(n, 0);
+			break;
+		case OCALLMETH:
+			cgen_callmeth(n, 0);
+			break;
+		case OCALLINTER:
+			cgen_callinter(n, N, 0);
+			break;
+		}
 		fp = structfirst(&flist, getoutarg(n->left->type));
-		cgen_call(n, 0);
 		memset(a, 0, sizeof *a);
 		a->op = OINDREG;
 		a->val.u.reg = D_SP;
 		gmove(&nodr, &nodl);
 
 		nodl.xoffset += Array_nel-Array_array;
-		nodl.type = types[TUINT32];
+		nodl.type = types[simtype[TUINT]];
 
 		if(nr != N) {
 			nodr.xoffset += Array_nel-Array_array;
 		gmove(&nodr, &nodl);
 
 		nodl.xoffset += Array_cap-Array_nel;
-		nodl.type = types[TUINT32];
+		nodl.type = types[simtype[TUINT]];
 
 		if(nr != N) {
 			nodr.xoffset += Array_cap-Array_nel;
 		gmove(&nodr, &nodl);
 
 		nodl.xoffset += Array_nel-Array_array;
-		nodl.type = types[TUINT32];
+		nodl.type = types[simtype[TUINT]];
 
 		if(nr != N) {
 			nodr.xoffset += Array_nel-Array_array;

File src/cmd/6g/galign.c

  */
 Typedef	typedefs[] =
 {
-	"int",		TINT,		TINT32,
-	"uint",		TUINT,		TUINT32,
+	"int",		TINT,		TINT64,
+	"uint",		TUINT,		TUINT64,
 	"uintptr",	TUINTPTR,	TUINT64,
 	0
 };
 betypeinit(void)
 {
 	widthptr = 8;
+	widthint = 8;
 
 	zprog.link = P;
 	zprog.as = AGOK;

File src/cmd/6g/gg.h

 	Sym*	gotype;
 	Sym*	sym;
 	Node*	node;
-	int	width;
+	int64	width;
 	uchar	type;
 	uchar	index;
 	uchar	etype;
 extern	vlong	unmappedzero;
 
 /*
- * gen.c
+ * ggen.c
  */
 void	compile(Node*);
 void	proglist(void);
 int	gen_as_init(Node*);
 
 /*
- * cgen
+ * cgen.c
  */
 void	agen(Node*, Node*);
 void	igen(Node*, Node*, Node*);
 void	proglist(void);
 Prog*	gbranch(int, Type*, int);
 Prog*	prog(int);
-void	gaddoffset(Node*);
 void	gconv(int, int);
 int	conv2pt(Type*);
 vlong	convvtox(vlong, int);
 void	sudoclean(void);
 int	sudoaddable(int, Node*, Addr*);
 void	afunclit(Addr*);
-void	datagostring(Strlit*, Addr*);
 void	nodfconst(Node*, Type*, Mpflt*);
 
 /*
  * gobj.c
  */
 void	datastring(char*, int, Addr*);
+void	datagostring(Strlit*, Addr*);
 
 /*
  * list.c

File src/cmd/6g/ggen.c

 /*
  * generate byte multiply:
  *	res = nl * nr
- * no 2-operand byte multiply instruction so have to do
- * 16-bit multiply and take bottom half.
+ * there is no 2-operand byte multiply instruction so
+ * we do a full-width multiplication and truncate afterwards.
  */
 void
 cgen_bmul(int op, Node *nl, Node *nr, Node *res)
 {
-	Node n1b, n2b, n1w, n2w;
+	Node n1, n2, *tmp;
 	Type *t;
 	int a;
 
-	if(nl->ullman >= nr->ullman) {
-		regalloc(&n1b, nl->type, res);
-		cgen(nl, &n1b);
-		regalloc(&n2b, nr->type, N);
-		cgen(nr, &n2b);
-	} else {
-		regalloc(&n2b, nr->type, N);
-		cgen(nr, &n2b);
-		regalloc(&n1b, nl->type, res);
-		cgen(nl, &n1b);
+	// copy from byte to full registers
+	t = types[TUINT64];
+	if(issigned[nl->type->etype])
+		t = types[TINT64];
+
+	// largest ullman on left.
+	if(nl->ullman < nr->ullman) {
+		tmp = nl;
+		nl = nr;
+		nr = tmp;
 	}
 
-	// copy from byte to short registers
-	t = types[TUINT16];
-	if(issigned[nl->type->etype])
-		t = types[TINT16];
-
-	regalloc(&n2w, t, &n2b);
-	cgen(&n2b, &n2w);
-
-	regalloc(&n1w, t, &n1b);
-	cgen(&n1b, &n1w);
-
+	regalloc(&n1, t, res);
+	cgen(nl, &n1);
+	regalloc(&n2, t, N);
+	cgen(nr, &n2);
 	a = optoas(op, t);
-	gins(a, &n2w, &n1w);
-	cgen(&n1w, &n1b);
-	cgen(&n1b, res);
-
-	regfree(&n1w);
-	regfree(&n2w);
-	regfree(&n1b);
-	regfree(&n2b);
+	gins(a, &n2, &n1);
+	regfree(&n2);
+	gmove(&n1, res);
+	regfree(&n1);
 }
 
 void

File src/cmd/6g/gobj.c

 	a->type = D_EXTERN;
 	a->sym = sym;
 	a->node = sym->def;
-	a->offset = widthptr+4;  // skip header
-	a->etype = TINT32;
+	a->offset = widthptr+widthint;  // skip header
+	a->etype = simtype[TINT];
 }
 
 /*
 datagostring(Strlit *sval, Addr *a)
 {
 	Sym *sym;
-	
+
 	sym = stringsym(sval->s, sval->len);
 	a->type = D_EXTERN;
 	a->sym = sym;
 	p->to.type = D_ADDR;
 //print("%P\n", p);
 
-	nodconst(&nod1, types[TINT32], sval->len);
+	nodconst(&nod1, types[TINT], sval->len);
 	p = gins(ADATA, nam, &nod1);
-	p->from.scale = types[TINT32]->width;
-	p->from.offset += types[tptr]->width;
+	p->from.scale = widthint;
+	p->from.offset += widthptr;
 }
 
 int
 	datastring(str, strlen(str)+1, &p->to);
 	p->to.index = p->to.type;
 	p->to.type = D_ADDR;
-	p->to.etype = TINT32;
+	p->to.etype = simtype[TINT];
 	off += widthptr;
 
 	return off;
 	datagostring(lit, &p->to);
 	p->to.index = p->to.type;
 	p->to.type = D_ADDR;
-	p->to.etype = TINT32;
+	p->to.etype = simtype[TINT];
 	off += widthptr;
 
 	return off;

File src/cmd/6g/gsubr.c

 	case AMOVSD:
 		if(f != N && t != N && samaddr(f, t))
 			return nil;
+		break;
+	
+	case ALEAQ:
+		if(f != N && isconst(f, CTNIL)) {
+			fatal("gins LEAQ nil %T", f->type);
+		}
+		break;
 	}
 
 	memset(&af, 0, sizeof af);
 		naddr(n->left, a, canemitcode);
 		if(a->type == D_CONST && a->offset == 0)
 			break;	// len(nil)
-		a->etype = TUINT32;
+		a->etype = simtype[TUINT];
 		a->offset += Array_nel;
-		a->width = 4;
+		a->width = widthint;
 		if(a->offset >= unmappedzero && a->offset-Array_nel < unmappedzero)
 			checkoffset(a, canemitcode);
 		break;
 		naddr(n->left, a, canemitcode);
 		if(a->type == D_CONST && a->offset == 0)
 			break;	// cap(nil)
-		a->etype = TUINT32;
+		a->etype = simtype[TUINT];
 		a->offset += Array_cap;
-		a->width = 4;
+		a->width = widthint;
 		if(a->offset >= unmappedzero && a->offset-Array_cap < unmappedzero)
 			checkoffset(a, canemitcode);
 		break;
 	if(!debug['B'] && !n->bounded) {
 		// check bounds
 		n4.op = OXXX;
-		t = types[TUINT32];
+		t = types[simtype[TUINT]];
 		if(o & ODynam) {
 			if(o & OAddable) {
 				n2 = *l;
 				n2.xoffset += Array_nel;
-				n2.type = types[TUINT32];
+				n2.type = types[simtype[TUINT]];
 				if(is64(r->type)) {
 					t = types[TUINT64];
 					regalloc(&n4, t, N);
 				n2 = *reg;
 				n2.xoffset = Array_nel;
 				n2.op = OINDREG;
-				n2.type = types[TUINT32];
+				n2.type = types[simtype[TUINT]];
 				if(is64(r->type)) {
 					t = types[TUINT64];
 					regalloc(&n4, t, N);
 			n1.type = types[tptr];
 			n1.xoffset = Array_nel;
 			nodconst(&n2, types[TUINT64], v);
-			gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
-			p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
+			gins(optoas(OCMP, types[simtype[TUINT]]), &n1, &n2);
+			p1 = gbranch(optoas(OGT, types[simtype[TUINT]]), T, +1);
 			ginscall(panicindex, -1);
 			patch(p1, pc);
 		}
 	if(!debug['B'] && !n->bounded) {
 		a->offset += Array_nel;
 		nodconst(&n2, types[TUINT64], v);
-		p1 = gins(optoas(OCMP, types[TUINT32]), N, &n2);
+		p1 = gins(optoas(OCMP, types[simtype[TUINT]]), N, &n2);
 		p1->from = *a;
-		p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
+		p1 = gbranch(optoas(OGT, types[simtype[TUINT]]), T, +1);
 		ginscall(panicindex, -1);
 		patch(p1, pc);
 		a->offset -= Array_nel;

File src/cmd/6g/opt.h

 #define	D_HI	D_NONE
 #define	D_LO	D_NONE
 
-#define	isregtype(t)	((t)>= D_AX && (t)<=D_R15)
-
 #define	BLOAD(r)	band(bnot(r->refbehind), r->refahead)
 #define	BSTORE(r)	band(bnot(r->calbehind), r->calahead)
 #define	LOAD(r)		(~r->refbehind.b[z] & r->refahead.b[z])
 typedef	struct	Reg	Reg;
 typedef	struct	Rgn	Rgn;
 
+// A Reg is a wrapper around a single Prog (one instruction) that holds
+// register optimization information while the optimizer runs.
+// r->prog is the instruction.
+// r->prog->regp points back to r.
 struct	Reg
 {
 
-	Bits	set;
-	Bits	use1;
-	Bits	use2;
+	Bits	set;  		// variables written by this instruction.
+	Bits	use1; 		// variables read by prog->from.
+	Bits	use2; 		// variables read by prog->to.
 
 	Bits	refbehind;
 	Bits	refahead;
 	uint16	loop;		// x5 for every loop
 	uchar	refset;		// diagnostic generated
 
-	Reg*	p1;
-	Reg*	p2;
+	Reg*	p1;     	// predecessors of this instruction: p1,
+	Reg*	p2;     	// and then p2 linked though p2link.
 	Reg*	p2link;
-	Reg*	s1;
+	Reg*	s1;     	// successors of this instruction (at most two: s1 and s2).
 	Reg*	s2;
-	Reg*	link;
-	Prog*	prog;
+	Reg*	link;   	// next instruction in function code
+	Prog*	prog;   	// actual instruction
 };
 #define	R	((Reg*)0)
 

File src/cmd/6g/reg.c

 	p1->as = AMOVL;
 	switch(v->etype) {
 	default:
-		fatal("unknown type\n");
+		fatal("unknown type %E", v->etype);
 	case TINT8:
 	case TUINT8:
 	case TBOOL:
 mkvar(Reg *r, Adr *a)
 {
 	Var *v;
-	int i, t, n, et, z, w, flag;
+	int i, t, n, et, z, flag;
+	int64 w;
 	uint32 regu;
 	int32 o;
 	Bits bit;
 	o = a->offset;
 	w = a->width;
 	if(w < 0)
-		fatal("bad width %d for %D", w, a);
+		fatal("bad width %lld for %D", w, a);
 
 	flag = 0;
 	for(i=0; i<nvar; i++) {
 	v->node = node;
 
 	if(debug['R'])
-		print("bit=%2d et=%2d w=%d+%d %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
+		print("bit=%2d et=%2E w=%d+%d %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
 
 	ostats.nvar++;
 
 
 /*
  *	bit	reg
- *	16	X5 (FREGMIN)
+ *	16	X0
  *	...
- *	26	X15 (FREGEXT)
+ *	31	X15
  */
 int32
 FtoB(int f)
 {
-	if(f < FREGMIN || f > FREGEXT)
+	if(f < D_X0 || f > D_X15)
 		return 0;
-	return 1L << (f - FREGMIN + 16);
+	return 1L << (f - D_X0 + 16);
 }
 
 int
 	b &= 0xFFFF0000L;
 	if(b == 0)
 		return 0;
-	return bitno(b) - 16 + FREGMIN;
+	return bitno(b) - 16 + D_X0;
 }
 
 void

File src/cmd/6l/6.out.h

 	
 	AUNDEF,
 
+	AAESENC,
+	AAESENCLAST,
+	AAESDEC,
+	AAESDECLAST,
+	AAESIMC,
+	AAESKEYGENASSIST,
+
+	APSHUFD,
+
 	ALAST
 };
 

File src/cmd/6l/l.h

 {
 	thechar = '6',
 	PtrSize = 8,
+	IntSize = 8,
 	
 	// Loop alignment constants:
 	// want to align loop entry to LoopAlign-byte boundary,

File src/cmd/6l/optab.c

 };
 uchar	yimul3[] =
 {
-	Yml,	Yrl,	Zibm_r,	1,
+	Yml,	Yrl,	Zibm_r,	2,
 	0
 };
 uchar	ybyte[] =
 };
 uchar	ymshuf[] =
 {
-	Ymm,	Ymr,	Zibm_r,	1,
+	Ymm,	Ymr,	Zibm_r,	2,
 	0
 };
 uchar	yxshuf[] =
 {
-	Yxm,	Yxr,	Zibm_r,	1,
+	Yxm,	Yxr,	Zibm_r,	2,
 	0
 };
 uchar	yextrw[] =
 {
-	Yxr,	Yrl,	Zibm_r,	1,
+	Yxr,	Yrl,	Zibm_r,	2,
 	0
 };
 uchar	ypsdq[] =
 	Ym,	Ynone,	Zm_o,	2,
 	0,
 };
+uchar	yaes[] =
+{
+	Yxm,	Yxr,	Zlitm_r,	2,
+	0
+};
+uchar	yaes2[] =
+{
+	Yxm,	Yxr,	Zibm_r,	2,
+	0
+};
 
 /*
  * You are doasm, holding in your hand a Prog* with p->as set to, say, ACRC32,
 	{ AIMULL,	yimul,	Px, 0xf7,(05),0x6b,0x69,Pm,0xaf },
 	{ AIMULQ,	yimul,	Pw, 0xf7,(05),0x6b,0x69,Pm,0xaf },
 	{ AIMULW,	yimul,	Pe, 0xf7,(05),0x6b,0x69,Pm,0xaf },
-	{ AIMUL3Q,	yimul3,	Pw, 0x6b },
+	{ AIMUL3Q,	yimul3,	Pw, 0x6b,(00) },
 	{ AINB,		yin,	Pb, 0xe4,0xec },
 	{ AINCB,	yincb,	Pb, 0xfe,(00) },
 	{ AINCL,	yincl,	Px, 0xff,(00) },
 	{ APCMPGTB,	ymm,	Py, 0x64,Pe,0x64 },
 	{ APCMPGTL,	ymm,	Py, 0x66,Pe,0x66 },
 	{ APCMPGTW,	ymm,	Py, 0x65,Pe,0x65 },
-	{ APEXTRW,	yextrw,	Pq, 0xc5 },
+	{ APEXTRW,	yextrw,	Pq, 0xc5,(00) },
 	{ APF2IL,	ymfp,	Px, 0x1d },
 	{ APF2IW,	ymfp,	Px, 0x1c },
 	{ API2FL,	ymfp,	Px, 0x0d },
 	{ APFRSQRT,	ymfp,	Px, 0x97 },
 	{ APFSUB,	ymfp,	Px, 0x9a },
 	{ APFSUBR,	ymfp,	Px, 0xaa },
-	{ APINSRW,	yextrw,	Pq, 0xc4 },
+	{ APINSRW,	yextrw,	Pq, 0xc4,(00) },
 	{ APMADDWL,	ymm,	Py, 0xf5,Pe,0xf5 },
 	{ APMAXSW,	yxm,	Pe, 0xee },
 	{ APMAXUB,	yxm,	Pe, 0xde },
 	{ APOPW,	ypopl,	Pe, 0x58,0x8f,(00) },
 	{ APOR,		ymm,	Py, 0xeb,Pe,0xeb },
 	{ APSADBW,	yxm,	Pq, 0xf6 },
-	{ APSHUFHW,	yxshuf,	Pf3, 0x70 },
-	{ APSHUFL,	yxshuf,	Pq, 0x70 },
-	{ APSHUFLW,	yxshuf,	Pf2, 0x70 },
-	{ APSHUFW,	ymshuf,	Pm, 0x70 },
+	{ APSHUFHW,	yxshuf,	Pf3, 0x70,(00) },
+	{ APSHUFL,	yxshuf,	Pq, 0x70,(00) },
+	{ APSHUFLW,	yxshuf,	Pf2, 0x70,(00) },
+	{ APSHUFW,	ymshuf,	Pm, 0x70,(00) },
 	{ APSLLO,	ypsdq,	Pq, 0x73,(07) },
 	{ APSLLL,	yps,	Py, 0xf2, 0x72,(06), Pe,0xf2, Pe,0x72,(06) },
 	{ APSLLQ,	yps,	Py, 0xf3, 0x73,(06), Pe,0xf3, Pe,0x73,(06) },
 	{ ASHRL,	yshl,	Px, 0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05) },
 	{ ASHRQ,	yshl,	Pw, 0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05) },
 	{ ASHRW,	yshl,	Pe, 0xd1,(05),0xc1,(05),0xd3,(05),0xd3,(05) },
-	{ ASHUFPD,	yxshuf,	Pq, 0xc6 },
-	{ ASHUFPS,	yxshuf,	Pm, 0xc6 },
+	{ ASHUFPD,	yxshuf,	Pq, 0xc6,(00) },
+	{ ASHUFPS,	yxshuf,	Pm, 0xc6,(00) },
 	{ ASQRTPD,	yxm,	Pe, 0x51 },
 	{ ASQRTPS,	yxm,	Pm, 0x51 },
 	{ ASQRTSD,	yxm,	Pf2, 0x51 },
 
 	{ AUNDEF,		ynone,	Px, 0x0f, 0x0b },
 
+	{ AAESENC,	yaes,	Pq, 0x38,0xdc,(0) },
+	{ AAESENCLAST,	yaes,	Pq, 0x38,0xdd,(0) },
+	{ AAESDEC,	yaes,	Pq, 0x38,0xde,(0) },
+	{ AAESDECLAST,	yaes,	Pq, 0x38,0xdf,(0) },
+	{ AAESIMC,	yaes,	Pq, 0x38,0xdb,(0) },
+	{ AAESKEYGENASSIST,	yaes2,	Pq, 0x3a,0xdf,(0) },
+
+	{ APSHUFD,	yaes2,	Pq,	0x70,(0) },
+
 	{ AEND },
 	0
 };

File src/cmd/6l/span.c

 		break;
 
 	case Zibm_r:
-		*andptr++ = op;
+		while ((op = o->op[z++]) != 0)
+			*andptr++ = op;
 		asmand(&p->from, &p->to);
 		*andptr++ = p->to.offset;
 		break;

File src/cmd/8g/cgen.c

 		}
 		if(isslice(nl->type)) {
 			igen(nl, &n1, res);
-			n1.op = OINDREG;
 			n1.type = types[TUINT32];
-			n1.xoffset = Array_cap;
+			n1.xoffset += Array_cap;
 			gmove(&n1, res);
 			regfree(&n1);
 			break;
 	while(n->op == OCONVNOP)
 		n = n->left;
 
+	if(isconst(n, CTNIL) && n->type->width > widthptr) {
+		// Use of a nil interface or nil slice.
+		// Create a temporary we can take the address of and read.
+		// The generated code is just going to panic, so it need not
+		// be terribly efficient. See issue 3670.
+		tempname(&n1, n->type);
+		clearfat(&n1);
+		regalloc(&n2, types[tptr], res);
+		gins(ALEAL, &n1, &n2);
+		gmove(&n2, res);
+		regfree(&n2);
+		return;
+	}
+		
 	// addressable var is easy
 	if(n->addable) {
 		if(n->op == OREGISTER)
 void
 igen(Node *n, Node *a, Node *res)
 {
-	Node n1;
 	Type *fp;
 	Iter flist;
-  
+	Node n1;
+
 	switch(n->op) {
 	case ONAME:
 		if((n->class&PHEAP) || n->class == PPARAMREF)
 		*a = *n;
 		return;
 
+	case OINDREG:
+		// Increase the refcount of the register so that igen's caller
+		// has to call regfree.
+		if(n->val.u.reg != D_SP)
+			reg[n->val.u.reg]++;
+		*a = *n;
+		return;
+
+	case ODOT:
+		igen(n->left, a, res);
+		a->xoffset += n->xoffset;
+		a->type = n->type;
+		return;
+
+	case ODOTPTR:
+		regalloc(a, types[tptr], res);
+		cgen(n->left, a);
+		if(n->xoffset != 0) {
+			// explicit check for nil if struct is large enough
+			// that we might derive too big a pointer.
+			if(n->left->type->type->width >= unmappedzero) {
+				n1 = *a;
+				n1.op = OINDREG;
+				n1.type = types[TUINT8];
+				n1.xoffset = 0;
+				gins(ATESTB, nodintconst(0), &n1);
+			}
+		}
+		a->op = OINDREG;
+		a->xoffset += n->xoffset;
+		a->type = n->type;
+		return;
+
 	case OCALLFUNC:
+	case OCALLMETH:
+	case OCALLINTER:
+		switch(n->op) {
+		case OCALLFUNC:
+			cgen_call(n, 0);
+			break;
+		case OCALLMETH:
+			cgen_callmeth(n, 0);
+			break;
+		case OCALLINTER:
+			cgen_callinter(n, N, 0);
+			break;
+		}
 		fp = structfirst(&flist, getoutarg(n->left->type));
-		cgen_call(n, 0);
 		memset(a, 0, sizeof *a);
 		a->op = OINDREG;
 		a->val.u.reg = D_SP;
 		a = optoas(a, nr->type);
 
 		if(nr->ullman >= UINF) {
-			tempname(&n1, nl->type);
-			tempname(&tmp, nr->type);
-			cgen(nl, &n1);
-			cgen(nr, &tmp);
+			if(!nl->addable) {
+				tempname(&n1, nl->type);
+				cgen(nl, &n1);
+				nl = &n1;
+			}
+			if(!nr->addable) {
+				tempname(&tmp, nr->type);
+				cgen(nr, &tmp);
+				nr = &tmp;
+			}
 			regalloc(&n2, nr->type, N);
-			cgen(&tmp, &n2);
+			cgen(nr, &n2);
 			goto cmp;
 		}
 
-		tempname(&n1, nl->type);
-		cgen(nl, &n1);
+		if(!nl->addable) {
+			tempname(&n1, nl->type);
+			cgen(nl, &n1);
+			nl = &n1;
+		}
 
 		if(smallintconst(nr)) {
-			gins(optoas(OCMP, nr->type), &n1, nr);
+			gins(optoas(OCMP, nr->type), nl, nr);
 			patch(gbranch(a, nr->type, likely), to);
 			break;
 		}
 
-		tempname(&tmp, nr->type);
-		cgen(nr, &tmp);
+		if(!nr->addable) {
+			tempname(&tmp, nr->type);
+			cgen(nr, &tmp);
+			nr = &tmp;
+		}
 		regalloc(&n2, nr->type, N);
-		gmove(&tmp, &n2);
+		gmove(nr, &n2);
 
 cmp:
-		gins(optoas(OCMP, nr->type), &n1, &n2);
+		gins(optoas(OCMP, nr->type), nl, &n2);
 		patch(gbranch(a, nr->type, likely), to);
 		regfree(&n2);
 		break;

File src/cmd/8g/galign.c

 betypeinit(void)
 {
 	widthptr = 4;
+	widthint = 4;
 
 	zprog.link = P;
 	zprog.as = AGOK;

File src/cmd/8g/gg.h

 void	proglist(void);
 Prog*	gbranch(int, Type*, int);
 Prog*	prog(int);
-void	gaddoffset(Node*);
 void	gconv(int, int);
 int	conv2pt(Type*);
 vlong	convvtox(vlong, int);
 void	fnparam(Type*, int, int);
 Prog*	gop(int, Node*, Node*, Node*);
-void	setconst(Addr*, vlong);
-void	setaddr(Addr*, Node*);
 int	optoas(int, Type*);
 int	foptoas(int, Type*, int);
 void	ginit(void);
 void	nodindreg(Node*, Type*, int);
 void	nodconst(Node*, Type*, int64);
 void	gconreg(int, vlong, int);
-void	datagostring(Strlit*, Addr*);
-void	datastring(char*, int, Addr*);
 void	buildtxt(void);
 Plist*	newplist(void);
 int	isfat(Type*);
 void	complexgen(Node*, Node*);
 
 /*
+ * gobj.c
+ */
+void	datastring(char*, int, Addr*);
+void	datagostring(Strlit*, Addr*);
+
+/*
  * list.c
  */
 int	Aconv(Fmt*);

File src/cmd/8g/ggen.c

 /*
  * generate byte multiply:
  *	res = nl * nr
- * no byte multiply instruction so have to do
- * 16-bit multiply and take bottom half.
+ * there is no 2-operand byte multiply instruction so
+ * we do a full-width multiplication and truncate afterwards.
  */
 void
 cgen_bmul(int op, Node *nl, Node *nr, Node *res)
 {
-	Node n1b, n2b, n1w, n2w;
+	Node n1, n2, *tmp;
 	Type *t;
 	int a;
 
-	if(nl->ullman >= nr->ullman) {
-		regalloc(&n1b, nl->type, res);
-		cgen(nl, &n1b);
-		regalloc(&n2b, nr->type, N);
-		cgen(nr, &n2b);
-	} else {
-		regalloc(&n2b, nr->type, N);
-		cgen(nr, &n2b);
-		regalloc(&n1b, nl->type, res);
-		cgen(nl, &n1b);
+	// copy from byte to full registers
+	t = types[TUINT32];
+	if(issigned[nl->type->etype])
+		t = types[TINT32];
+
+	// largest ullman on left.
+	if(nl->ullman < nr->ullman) {
+		tmp = nl;
+		nl = nr;
+		nr = tmp;
 	}
 
-	// copy from byte to short registers
-	t = types[TUINT16];
-	if(issigned[nl->type->etype])
-		t = types[TINT16];
+	regalloc(&n1, t, res);
+	cgen(nl, &n1);
+	regalloc(&n2, t, N);
+	cgen(nr, &n2);
+	a = optoas(op, t);
+	gins(a, &n2, &n1);
+	regfree(&n2);
+	gmove(&n1, res);
+	regfree(&n1);
+}
 
-	regalloc(&n2w, t, &n2b);
-	cgen(&n2b, &n2w);
-
-	regalloc(&n1w, t, &n1b);
-	cgen(&n1b, &n1w);
-
-	a = optoas(op, t);
-	gins(a, &n2w, &n1w);
-	cgen(&n1w, &n1b);
-	cgen(&n1b, res);
-
-	regfree(&n1w);
-	regfree(&n2w);
-	regfree(&n1b);
-	regfree(&n2b);
-}

File src/cmd/8g/gsubr.c

 
 	for(i=0; i<nelem(reg); i++)
 		reg[i] = 1;
-	for(i=D_AL; i<=D_DI; i++)
+	for(i=D_AX; i<=D_DI; i++)
 		reg[i] = 0;
 	for(i=0; i<nelem(resvd); i++)
 		reg[resvd[i]]++;
 	for(i=0; i<nelem(resvd); i++)
 		reg[resvd[i]]--;
 
-	for(i=D_AL; i<=D_DI; i++)
+	for(i=D_AX; i<=D_DI; i++)
 		if(reg[i])
 			yyerror("reg %R left allocated at %ux", i, regpc[i]);
 }
 {
 	int i, j;
 
-	for(i=D_AL; i<=D_DI; i++) {
+	for(i=D_AX; i<=D_DI; i++) {
 		if(reg[i] == 0)
 			goto ok;
 		for(j=0; j<nelem(resvd); j++)
 	case AMOVL:
 		if(f != N && t != N && samaddr(f, t))
 			return nil;
+		break;
+	
+	case ALEAL:
+		if(f != N && isconst(f, CTNIL))
+			fatal("gins LEAQ nil %T", f->type);
+		break;
 	}
 
 	memset(&af, 0, sizeof af);

File src/cmd/8g/opt.h

 typedef	struct	Reg	Reg;
 typedef	struct	Rgn	Rgn;
 
+// A Reg is a wrapper around a single Prog (one instruction) that holds
+// register optimization information while the optimizer runs.
+// r->prog is the instruction.
+// r->prog->regp points back to r.
 struct	Reg
 {
 
-	Bits	set;
-	Bits	use1;
-	Bits	use2;
+	Bits	set;  		// variables written by this instruction.
+	Bits	use1; 		// variables read by prog->from.
+	Bits	use2; 		// variables read by prog->to.
 
 	Bits	refbehind;
 	Bits	refahead;
 	uint16	loop;		// x5 for every loop
 	uchar	refset;		// diagnostic generated
 
-	Reg*	p1;
-	Reg*	p2;
+	Reg*	p1;     	// predecessors of this instruction: p1,
+	Reg*	p2;     	// and then p2 linked though p2link.
 	Reg*	p2link;
-	Reg*	s1;
+	Reg*	s1;     	// successors of this instruction (at most two: s1 and s2).
 	Reg*	s2;
-	Reg*	link;
-	Prog*	prog;
+	Reg*	link;   	// next instruction in function code
+	Prog*	prog;   	// actual instruction
 };
 #define	R	((Reg*)0)
 

File src/cmd/8g/reg.c

 	v->node = node;
 
 	if(debug['R'])
-		print("bit=%2d et=%2d w=%d+%d %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
+		print("bit=%2d et=%2E w=%d+%d %#N %D flag=%d\n", i, et, o, w, node, a, v->addr);
 	ostats.nvar++;
 
 	bit = blsh(i);

File src/cmd/8l/l.h

 {
 	thechar = '8',
 	PtrSize = 4,
+	IntSize = 4,
 	FuncAlign = 16
 };
 

File src/cmd/api/goapi.go

 func main() {
 	flag.Parse()
 
-	if !strings.Contains(runtime.Version(), "weekly") && runtime.Version() != "devel" {
+	if !strings.Contains(runtime.Version(), "weekly") && !strings.Contains(runtime.Version(), "devel") {
 		if *nextFile != "" {
 			fmt.Printf("Go version is %q, ignoring -next %s\n", runtime.Version(), *nextFile)
 			*nextFile = ""
 		}
 	}
 
+	// In next file, but not in API.
 	var missing []string
 	for feature := range optional {
 		missing = append(missing, feature)
 	}
 	sort.Strings(missing)
 	for _, feature := range missing {
-		fmt.Fprintf(bw, "(in next file, but not in API) -%s\n", feature)
+		fmt.Fprintf(bw, "±%s\n", feature)
 	}
 }
 

File src/cmd/cgo/gcc.go

 
 	// Record types and typedef information.
 	var conv typeConv
-	conv.Init(p.PtrSize)
+	conv.Init(p.PtrSize, p.IntSize)
 	for i, n := range names {
 		if types[i] == nil {
 			continue
 	string                                 ast.Expr
 
 	ptrSize int64
+	intSize int64
 }
 
 var tagGen int
 var typedef = make(map[string]*Type)
 var goIdent = make(map[string]*ast.Ident)
 
-func (c *typeConv) Init(ptrSize int64) {
+func (c *typeConv) Init(ptrSize, intSize int64) {
 	c.ptrSize = ptrSize
+	c.intSize = intSize
 	c.m = make(map[dwarf.Type]*Type)
 	c.bool = c.Ident("bool")
 	c.byte = c.Ident("byte")

File src/cmd/cgo/main.go

 	PackageName string // name of package
 	PackagePath string
 	PtrSize     int64
+	IntSize     int64
 	GccOptions  []string
 	CgoFlags    map[string]string // #cgo flags (CFLAGS, LDFLAGS)
 	Written     map[string]bool
 	"arm":   4,
 }
 
+var intSizeMap = map[string]int64{
+	"386":   4,
+	"amd64": 8,
+	"arm":   4,
+}
+
 var cPrefix string