Commits

Joseph Poirier committed 1d84114 Merge

Merged changes from golang.

Comments (0)

Files changed (223)

 ngmoco, LLC
 Nicholas Waples <nwaples@gmail.com>
 Nigel Kerr <nigel.kerr@gmail.com>
+Oling Cat <olingcat@gmail.com>
 Olivier Antoine <olivier.antoine@gmail.com>
 Olivier Duperray <duperray.olivier@gmail.com>
 Padraig Kitterick <padraigkitterick@gmail.com>
 Paolo Giarrusso <p.giarrusso@gmail.com>
 Pascal S. de Kloe <pascal@quies.net>
+Patrick Crosby <patrick@stathat.com>
 Patrick Gavlin <pgavlin@gmail.com>
+Patrick Higgins <patrick.allen.higgins@gmail.com>
 Patrick Mylund Nielsen <patrick@patrickmn.com>
 Paul Lalonde <paul.a.lalonde@gmail.com>
 Paul Sbarra <Sbarra.Paul@gmail.com>
 Sergei Skorobogatov <skorobo@rambler.ru>
 Sergey 'SnakE'  Gromov <snake.scaly@gmail.com>
 Sergio Luis O. B. Correia <sergio@larces.uece.br>
+Shawn Smith <shawn.p.smith@gmail.com>
 Shenghou Ma <minux.ma@gmail.com>
 Spring Mc <heresy.mc@gmail.com>
 Stefan Nilsson <snilsson@nada.kth.se> <trolleriprofessorn@gmail.com>
 Tobias Columbus <tobias.columbus@gmail.com>
 Tor Andersson <tor.andersson@gmail.com>
 Ugorji Nwoke <ugorji@gmail.com>
+Uriel Mangado <uriel@berlinblue.org>
 Vadim Vygonets <unixdj@gmail.com>
 Vincent Ambo <tazjin@googlemail.com>
 Vincent Vanackere <vincent.vanackere@gmail.com>
 Adam Langley <agl@golang.org>
 Adrian O'Grady <elpollouk@gmail.com>
 Akshat Kumar <seed@mail.nanosouffle.net>
+Alan Donovan <adonovan@google.com>
 Albert Strasheim <fullung@gmail.com>
 Aleksandar Dezelin <dezelin@gmail.com>
 Alex Brainman <alex.brainman@gmail.com>
 Lucio De Re <lucio.dere@gmail.com>
 Luit van Drongelen <luitvd@gmail.com>
 Luuk van Dijk <lvd@golang.org> <lvd@google.com>
+Manu Garg <manugarg@google.com>
 Marcel van Lohuizen <mpvl@golang.org>
 Mark Zavislak <zavislak@google.com>
 Markus Duft <markus.duft@salomon.at>
 Nicholas Waples <nwaples@gmail.com>
 Nigel Kerr <nigel.kerr@gmail.com>
 Nigel Tao <nigeltao@golang.org>
+Oling Cat <olingcat@gmail.com>
 Olivier Antoine <olivier.antoine@gmail.com>
 Olivier Duperray <duperray.olivier@gmail.com>
 Padraig Kitterick <padraigkitterick@gmail.com>
 Paolo Giarrusso <p.giarrusso@gmail.com>
 Pascal S. de Kloe <pascal@quies.net>
+Patrick Crosby <patrick@stathat.com>
 Patrick Gavlin <pgavlin@gmail.com>
+Patrick Higgins <patrick.allen.higgins@gmail.com>
 Patrick Mylund Nielsen <patrick@patrickmn.com>
 Paul Borman <borman@google.com>
 Paul Lalonde <paul.a.lalonde@gmail.com>
 Sergei Skorobogatov <skorobo@rambler.ru>
 Sergey 'SnakE' Gromov <snake.scaly@gmail.com>
 Sergio Luis O. B. Correia <sergio@larces.uece.br>
+Shawn Smith <shawn.p.smith@gmail.com>
 Shenghou Ma <minux.ma@gmail.com>
 Spring Mc <heresy.mc@gmail.com>
 Stefan Nilsson <snilsson@nada.kth.se> <trolleriprofessorn@gmail.com>
 Taru Karttunen <taruti@taruti.net>
 Thomas Alan Copeland <talan.copeland@gmail.com>
 Timo Savola <timo.savola@gmail.com>
-Tobias Columbus <tobias.columbus@gmail.com>
+Tobias Columbus <tobias.columbus@gmail.com> <tobias.columbus@googlemail.com>
 Tom Szymanski <tgs@google.com>
 Tor Andersson <tor.andersson@gmail.com>
 Trevor Strohman <trevor.strohman@gmail.com>
 Ugorji Nwoke <ugorji@gmail.com>
+Uriel Mangado <uriel@berlinblue.org>
 Vadim Vygonets <unixdj@gmail.com>
 Vincent Ambo <tazjin@googlemail.com>
 Vincent Vanackere <vincent.vanackere@gmail.com>
 
 clean:
 	rm -f $(RAWHTML)
+
+compare:
+	for i in $(RAWHTML); do \
+		godoc -url /doc/$${i/.rawhtml/.html} | diff -u $$i -; \
+	done

doc/articles/concurrency_patterns.html

 </p>
 
 <p>
-This problem is a textbook of example of what is known as a
+This problem is a textbook example of what is known as a
 <a href="https://en.wikipedia.org/wiki/Race_condition">race condition</a>, but
 the fix is trivial. We just make sure to buffer the channel <code>ch</code> (by
 adding the buffer length as the second argument to <a href="/pkg/builtin/#make">make</a>),
 the language specification, both of which should be read first.
 </p>
 
+<h3 id="ref"><a href="/ref/">Go References</a></h3>
+<p>Language specification, memory model, and detailed documentation for the commands and packages.</p>
+
 <h3 id="appengine"><a href="https://developers.google.com/appengine/docs/go/gettingstarted/">Getting Started with Go on App Engine</a></h3>
 <p>
 How to develop and deploy a simple Go project with

doc/effective_go.html

 Here's the complete program.
 An explanation follows.
 </p>
-{{code "/doc/progs/eff_qr.go"}}
+{{code "/doc/progs/eff_qr.go" `/package/` `$`}}
 <p>
 The pieces up to <code>main</code> should be easy to follow.
 The one flag sets a default HTTP port for our server.  The template
 <p>
 A Go type satisfies an interface by implementing the methods of that interface,
 nothing more.  This property allows interfaces to be defined and used without
-having to modify existing code.  It enables a kind of "duck typing" that
+having to modify existing code.  It enables a kind of structural typing that
 promotes separation of concerns and improves code re-use, and makes it easier
 to build on patterns that emerge as the code develops.
 The semantics of interfaces is one of the main reasons for Go's nimble,
 for more information about how to proceed.
 </p>
 
+<h3 id="Why_does_the_project_use_Mercurial_and_not_git">
+Why does the project use Mercurial and not git?</h3>
+
+<p>
+The Go project, hosted by Google Code at
+<a href="http://code.google.com/p/go">code.google.com/p/go</a>,
+uses Mercurial as its version control system.
+When the project launched,
+Google Code supported only Subversion and Mercurial.
+Mercurial was a better choice because of its plugin mechanism
+that allowed us to create the "codereview" plugin to connect
+the project to the excellent code review tools at 
+<a href="http://codereview.appspot.com">codereview.appspot.com</a>.
+</p>
+
+<p>
+Programmers who work
+with the Go project's source rather than release downloads sometimes
+ask for the project to switch to git.
+That would be possible, but it would be a lot of work and
+would also require reimplementing the codereview plugin.
+Given that Mercurial works today, with code review support,
+combined with the Go project's mostly linear, non-branching use of
+version control, a switch to git doesn't seem worthwhile.
+</p>
+
 <h2 id="Pointers">Pointers and Allocation</h2>
 
 <h3 id="pass_by_value">
 </p>
 
 <p>
-To bind the value of <code>v</code> to each closure as they are launched, one
-could modify the inner loop to read:
+To bind the current value of <code>v</code> to each closure as it is launched, one
+must modify the inner loop to create a new variable each iteration.
+One way is to pass the variable as an argument to the closure:
 </p>
 
 <pre>
 the variable <code>u</code>.
 </p>
 
+<p>
+Even easier is just to create a new variable, using a declaration style that may
+seem odd but works fine in Go:
+</p>
+
+<pre>
+    for _, v := range values {
+        <b>v := v</b> // create a new 'v'.
+        go func() {
+            fmt.Println(<b>v</b>)
+            done &lt;- true
+        }()
+    }
+</pre>
+
 <h2 id="Control_flow">Control flow</h2>
 
 <h3 id="Does_Go_have_a_ternary_form">
 <!--{
 	"Title": "The Go Programming Language Specification",
-	"Subtitle": "Version of August 17, 2012",
+	"Subtitle": "Version of September 7, 2012",
 	"Path": "/ref/spec"
 }-->
 
 canonicalized, so a single accented code point is distinct from the
 same character constructed from combining an accent and a letter;
 those are treated as two code points.  For simplicity, this document
-will use the term <i>character</i> to refer to a Unicode code point.
+will use the unqualified term <i>character</i> to refer to a Unicode code point
+in the source text.
 </p>
 <p>
 Each code point is distinct; for instance, upper and lower case letters
 Implementation restriction: For compatibility with other tools, a
 compiler may disallow the NUL character (U+0000) in the source text.
 </p>
+<p>
+Implementation restriction: For compatibility with other tools, a
+compiler may ignore a UTF-8-encoded byte order mark
+(U+FEFF) if it is the first Unicode code point in the source text.
+</p>
 
 <h3 id="Characters">Characters</h3>
 
 	    <a href="#Integer_literals">integer</a>,
 	    <a href="#Floating-point_literals">floating-point</a>,
 	    <a href="#Imaginary_literals">imaginary</a>,
-	    <a href="#Character_literals">character</a>, or
+	    <a href="#Rune_literals">rune</a>, or
 	    <a href="#String_literals">string</a> literal
 	</li>
 
 </pre>
 
 
-<h3 id="Character_literals">Character literals</h3>
-
-<p>
-A character literal represents a <a href="#Constants">character constant</a>,
-typically a Unicode code point, as one or more characters enclosed in single
-quotes.  Within the quotes, any character may appear except single
-quote and newline. A single quoted character represents itself,
+<h3 id="Rune_literals">Rune literals</h3>
+
+<p>
+A rune literal represents a <a href="#Constants">rune constant</a>,
+an integer value identifying a Unicode code point.
+A rune literal is expressed as one or more characters enclosed in single quotes.
+Within the quotes, any character may appear except single
+quote and newline. A single quoted character represents the Unicode value
+of the character itself,
 while multi-character sequences beginning with a backslash encode
 values in various formats.
 </p>
 a literal <code>a</code>-dieresis, U+00E4, value <code>0xe4</code>.
 </p>
 <p>
-Several backslash escapes allow arbitrary values to be represented
-as ASCII text.  There are four ways to represent the integer value
+Several backslash escapes allow arbitrary values to be encoded as
+ASCII text.  There are four ways to represent the integer value
 as a numeric constant: <code>\x</code> followed by exactly two hexadecimal
 digits; <code>\u</code> followed by exactly four hexadecimal digits;
 <code>\U</code> followed by exactly eight hexadecimal digits, and a
 \t   U+0009 horizontal tab
 \v   U+000b vertical tab
 \\   U+005c backslash
-\'   U+0027 single quote  (valid escape only within character literals)
+\'   U+0027 single quote  (valid escape only within rune literals)
 \"   U+0022 double quote  (valid escape only within string literals)
 </pre>
 <p>
-All other sequences starting with a backslash are illegal inside character literals.
+All other sequences starting with a backslash are illegal inside rune literals.
 </p>
 <pre class="ebnf">
 char_lit         = "'" ( unicode_value | byte_value ) "'" .
 '\xff'
 '\u12e4'
 '\U00101234'
+'aa'         // illegal: too many characters
+'\xa'        // illegal: too few hexadecimal digits
+'\0'         // illegal: too few octal digits
+'\uDFFF'     // illegal: surrogate half
+'\U00110000' // illegal: invalid Unicode code point
 </pre>
 
 
 Raw string literals are character sequences between back quotes
 <code>``</code>.  Within the quotes, any character is legal except
 back quote. The value of a raw string literal is the
-string composed of the uninterpreted characters between the quotes;
+string composed of the uninterpreted (implicitly UTF-8-encoded) characters
+between the quotes;
 in particular, backslashes have no special meaning and the string may
 contain newlines.
 Carriage returns inside raw string literals
 quotes <code>&quot;&quot;</code>. The text between the quotes,
 which may not contain newlines, forms the
 value of the literal, with backslash escapes interpreted as they
-are in character literals (except that <code>\'</code> is illegal and
-<code>\"</code> is legal).  The three-digit octal (<code>\</code><i>nnn</i>)
+are in rune literals (except that <code>\'</code> is illegal and
+<code>\"</code> is legal), with the same restrictions.
+The three-digit octal (<code>\</code><i>nnn</i>)
 and two-digit hexadecimal (<code>\x</code><i>nn</i>) escapes represent individual
 <i>bytes</i> of the resulting string; all other escapes represent
 the (possibly multi-byte) UTF-8 encoding of individual <i>characters</i>.
 "日本語"
 "\u65e5本\U00008a9e"
 "\xff\u00FF"
+"\uD800"       // illegal: surrogate half
+"\U00110000"   // illegal: invalid Unicode code point
 </pre>
 
 <p>
 <pre>
 "日本語"                                 // UTF-8 input text
 `日本語`                                 // UTF-8 input text as a raw literal
-"\u65e5\u672c\u8a9e"                    // The explicit Unicode code points
-"\U000065e5\U0000672c\U00008a9e"        // The explicit Unicode code points
-"\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"  // The explicit UTF-8 bytes
+"\u65e5\u672c\u8a9e"                    // the explicit Unicode code points
+"\U000065e5\U0000672c\U00008a9e"        // the explicit Unicode code points
+"\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"  // the explicit UTF-8 bytes
 </pre>
 
 <p>
 If the source code represents a character as two code points, such as
 a combining form involving an accent and a letter, the result will be
-an error if placed in a character literal (it is not a single code
+an error if placed in a rune literal (it is not a single code
 point), and will appear as two code points if placed in a string
 literal.
 </p>
 <h2 id="Constants">Constants</h2>
 
 <p>There are <i>boolean constants</i>,
-<i>character constants</i>,
+<i>rune constants</i>,
 <i>integer constants</i>,
 <i>floating-point constants</i>, <i>complex constants</i>,
 and <i>string constants</i>. Character, integer, floating-point,
 
 <p>
 A constant value is represented by a
-<a href="#Character_literals">character</a>,
+<a href="#Rune_literals">rune</a>,
 <a href="#Integer_literals">integer</a>,
 <a href="#Floating-point_literals">floating-point</a>,
 <a href="#Imaginary_literals">imaginary</a>,
 If <code>x</code> is of pointer or interface type and has the value
 <code>nil</code>, assigning to, evaluating, or calling <code>x.f</code>
 causes a <a href="#Run_time_panics">run-time panic</a>.
-</i>
+</li>
 </ol>
 
 <p>
 respectively.
 Except for shift operations, if the operands of a binary operation are
 different kinds of untyped constants, the operation and, for non-boolean operations, the result use
-the kind that appears later in this list: integer, character, floating-point, complex.
+the kind that appears later in this list: integer, rune, floating-point, complex.
 For example, an untyped integer constant divided by an
 untyped complex constant yields an untyped complex constant.
 </p>
 const g = float64(2) &gt;&gt; 1  // illegal    (float64(2) is a typed floating-point constant)
 const h = "foo" &gt; "bar"    // h == true  (untyped boolean constant)
 const j = true             // j == true  (untyped boolean constant)
-const k = 'w' + 1          // k == 'x'   (untyped character constant)
+const k = 'w' + 1          // k == 'x'   (untyped rune constant)
 const l = "hi"             // l == "hi"  (untyped string constant)
 const m = string(k)        // m == "x"   (type string)
 const Σ = 1 - 0.707i       //            (untyped complex constant)
 
 <p>
 Applying the built-in function <code>complex</code> to untyped
-integer, character, or floating-point constants yields
+integer, rune, or floating-point constants yields
 an untyped complex constant.
 </p>
 
 to type <code>bool</code>, <code>rune</code>, <code>int</code>, <code>float64</code>,
 <code>complex128</code> or <code>string</code>
 respectively, depending on whether the value is a
-boolean, character, integer, floating-point, complex, or string constant.
+boolean, rune, integer, floating-point, complex, or string constant.
 </p>
 
 
 Calls to <code>Alignof</code>, <code>Offsetof</code>, and
 <code>Sizeof</code> are compile-time constant expressions of type <code>uintptr</code>.
 </p>
-<p>
 
 <h3 id="Size_and_alignment_guarantees">Size and alignment guarantees</h3>
 

doc/progs/cgo1.go

+// skip
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/cgo2.go

+// skip
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/cgo3.go

+// skip
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/cgo4.go

+// skip
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/defer.go

+// cmpout
+
 // Copyright 2011 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/defer.out

+0
+3210
+2

doc/progs/defer2.go

+// cmpout
+
 // Copyright 2011 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/defer2.out

+Calling g.
+Printing in g 0
+Printing in g 1
+Printing in g 2
+Printing in g 3
+Panicking!
+Defer in g 3
+Defer in g 2
+Defer in g 1
+Defer in g 0
+Recovered in f 4
+Returned normally from f.

doc/progs/eff_bytesize.go

+// cmpout
+
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/eff_bytesize.out

+1.00YB 9.09TB

doc/progs/eff_qr.go

+// compile
+
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
 package main
 
 import (

doc/progs/eff_sequence.go

+// cmpout
+
 // Copyright 2009 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/eff_sequence.out

+[-1 2 6 16 44]

doc/progs/error.go

+// compile
+
 // Copyright 2011 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/error2.go

+// compile
+
 // Copyright 2011 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/error3.go

+// compile
+
 // Copyright 2011 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/error4.go

+// compile
+
 // Copyright 2011 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
+// compile
+// this file will output a list of filenames in cwd, not suitable for cmpout
+
 // Copyright 2011 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/gobs1.go

+// compile
+
 // Copyright 2011 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/gobs2.go

+// compile
+
 // Copyright 2011 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/image_draw.go

+// compile
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/image_package1.go

+// cmpout
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/image_package1.out

+X is 2 Y is 1

doc/progs/image_package2.go

+// cmpout
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/image_package2.out

+3 4 false

doc/progs/image_package3.go

+// cmpout
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/image_package3.out

+3 4 true

doc/progs/image_package4.go

+// cmpout
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/image_package4.out

+image.Point{X:2, Y:1}

doc/progs/image_package5.go

+// cmpout
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/image_package5.out

+{255 0 0 255}

doc/progs/image_package6.go

+// cmpout
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/image_package6.out

+8 4
+true

doc/progs/interface.go

+// compile
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/interface2.go

+// cmpout
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/interface2.out

+type: float64

doc/progs/json1.go

+// run
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/json2.go

+// cmpout
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/json2.out

+the circle's area 24.227111172875365
+the reciprocal of i is 0.3601008282319049

doc/progs/json3.go

+// compile
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/json4.go

+// run
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/json5.go

+// compile
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/slices.go

+// compile
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/timeout1.go

+// compile
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/timeout2.go

+// compile
+
 // Copyright 2012 The Go Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.

doc/progs/update.bash

+#!/usr/bin/env bash
+# Copyright 2012 The Go Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style
+# license that can be found in the LICENSE file.
+
+set -e
+
+rm -f *.out *.rej *.orig [568].out
+
+for i in *.go; do
+	if grep -q '^// cmpout$' $i; then
+		echo $i
+		go run $i &> ${i/.go/.out}
+	fi
+done

include/plan9/amd64/u.h

+// Copyright 2012 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "/amd64/include/u.h"
+
+typedef char   int8;
+typedef uchar  uint8;
+typedef short  int16;
+typedef ushort uint16;
+typedef int    int32;
+typedef uint   uint32;
+typedef vlong  int64;
+typedef uvlong uint64;

lib/codereview/codereview.py

 #######################################################################
 # Commands added by code review extension.
 
-# As of Mercurial 2.1 the commands are all required to return integer
-# exit codes, whereas earlier versions allowed returning arbitrary strings
-# to be printed as errors.  We wrap the old functions to make sure we
-# always return integer exit codes now.  Otherwise Mercurial dies
-# with a TypeError traceback (unsupported operand type(s) for &: 'str' and 'int').
-# Introduce a Python decorator to convert old functions to the new
-# stricter convention.
-
 def hgcommand(f):
-	def wrapped(ui, repo, *pats, **opts):
-		err = f(ui, repo, *pats, **opts)
-		if type(err) is int:
-			return err
-		if not err:
-			return 0
-		raise hg_util.Abort(err)
-	wrapped.__doc__ = f.__doc__
-	return wrapped
+	return f
 
 #######################################################################
 # hg change
 	"""
 
 	if codereview_disabled:
-		return codereview_disabled
+		raise hg_util.Abort(codereview_disabled)
 	
 	dirty = {}
 	if len(pats) > 0 and GoodCLName(pats[0]):
 		name = pats[0]
 		if len(pats) != 1:
-			return "cannot specify CL name and file patterns"
+			raise hg_util.Abort("cannot specify CL name and file patterns")
 		pats = pats[1:]
 		cl, err = LoadCL(ui, repo, name, web=True)
 		if err != '':
-			return err
+			raise hg_util.Abort(err)
 		if not cl.local and (opts["stdin"] or not opts["stdout"]):
-			return "cannot change non-local CL " + name
+			raise hg_util.Abort("cannot change non-local CL " + name)
 	else:
 		name = "new"
 		cl = CL("new")
 		if repo[None].branch() != "default":
-			return "cannot create CL outside default branch; switch with 'hg update default'"
+			raise hg_util.Abort("cannot create CL outside default branch; switch with 'hg update default'")
 		dirty[cl] = True
 		files = ChangedFiles(ui, repo, pats, taken=Taken(ui, repo))
 
 	if opts["delete"] or opts["deletelocal"]:
 		if opts["delete"] and opts["deletelocal"]:
-			return "cannot use -d and -D together"
+			raise hg_util.Abort("cannot use -d and -D together")
 		flag = "-d"
 		if opts["deletelocal"]:
 			flag = "-D"
 		if name == "new":
-			return "cannot use "+flag+" with file patterns"
+			raise hg_util.Abort("cannot use "+flag+" with file patterns")
 		if opts["stdin"] or opts["stdout"]:
-			return "cannot use "+flag+" with -i or -o"
+			raise hg_util.Abort("cannot use "+flag+" with -i or -o")
 		if not cl.local:
-			return "cannot change non-local CL " + name
+			raise hg_util.Abort("cannot change non-local CL " + name)
 		if opts["delete"]:
 			if cl.copied_from:
-				return "original author must delete CL; hg change -D will remove locally"
+				raise hg_util.Abort("original author must delete CL; hg change -D will remove locally")
 			PostMessage(ui, cl.name, "*** Abandoned ***", send_mail=cl.mailed)
 			EditDesc(cl.name, closed=True, private=cl.private)
 		cl.Delete(ui, repo)
 		s = sys.stdin.read()
 		clx, line, err = ParseCL(s, name)
 		if err != '':
-			return "error parsing change list: line %d: %s" % (line, err)
+			raise hg_util.Abort("error parsing change list: line %d: %s" % (line, err))
 		if clx.desc is not None:
 			cl.desc = clx.desc;
 			dirty[cl] = True
 			cl.files = files
 		err = EditCL(ui, repo, cl)
 		if err != "":
-			return err
+			raise hg_util.Abort(err)
 		dirty[cl] = True
 
 	for d, _ in dirty.items():
 	a file in your home directory.
 	"""
 	if codereview_disabled:
-		return codereview_disabled
+		raise hg_util.Abort(codereview_disabled)
 
 	MySend(None)
 
 	name as the Author: line but add your own name to a Committer: line.
 	"""
 	if repo[None].branch() != "default":
-		return "cannot run hg clpatch outside default branch"
-	return clpatch_or_undo(ui, repo, clname, opts, mode="clpatch")
+		raise hg_util.Abort("cannot run hg clpatch outside default branch")
+	err = clpatch_or_undo(ui, repo, clname, opts, mode="clpatch")
+	if err:
+		raise hg_util.Abort(err)
 
 @hgcommand
 def undo(ui, repo, clname, **opts):
 	you can add the reason for the undo to the description.
 	"""
 	if repo[None].branch() != "default":
-		return "cannot run hg undo outside default branch"
-	return clpatch_or_undo(ui, repo, clname, opts, mode="undo")
+		raise hg_util.Abort("cannot run hg undo outside default branch")
+	err = clpatch_or_undo(ui, repo, clname, opts, mode="undo")
+	if err:
+		raise hg_util.Abort(err)
 
 @hgcommand
 def release_apply(ui, repo, clname, **opts):
 	"""
 	c = repo[None]
 	if not releaseBranch:
-		return "no active release branches"
+		raise hg_util.Abort("no active release branches")
 	if c.branch() != releaseBranch:
 		if c.modified() or c.added() or c.removed():
 			raise hg_util.Abort("uncommitted local changes - cannot switch branches")
 		err = hg_clean(repo, releaseBranch)
 		if err:
-			return err
+			raise hg_util.Abort(err)
 	try:
 		err = clpatch_or_undo(ui, repo, clname, opts, mode="backport")
 		if err:
 	except Exception, e:
 		hg_clean(repo, "default")
 		raise e
-	return None
 
 def rev2clname(rev):
 	# Extract CL name from revision description.
 	followed by its diff, downloaded from the code review server.
 	"""
 	if codereview_disabled:
-		return codereview_disabled
+		raise hg_util.Abort(codereview_disabled)
 
 	cl, vers, patch, err = DownloadCL(ui, repo, clname)
 	if err != "":
 	It does not edit them or remove them from the repository.
 	"""
 	if codereview_disabled:
-		return codereview_disabled
+		raise hg_util.Abort(codereview_disabled)
 
 	pats = tuple([pat] + list(pats))
 	if not GoodCLName(clname):
 	the given patterns.
 	"""
 	if codereview_disabled:
-		return codereview_disabled
+		raise hg_util.Abort(codereview_disabled)
 
 	files = ChangedExistingFiles(ui, repo, pats, opts)
 	files = gofmt_required(files)
 	to the reviewer and CC list asking for a review.
 	"""
 	if codereview_disabled:
-		return codereview_disabled
+		raise hg_util.Abort(codereview_disabled)
 
 	cl, err = CommandLineCL(ui, repo, pats, opts, defaultcc=defaultcc)
 	if err != "":
 	Lists pending changes followed by a list of unassigned but modified files.
 	"""
 	if codereview_disabled:
-		return codereview_disabled
+		raise hg_util.Abort(codereview_disabled)
 
 	quick = opts.get('quick', False)
 	short = opts.get('short', False)
 	Bails out if the local repository is not in sync with the remote one.
 	"""
 	if codereview_disabled:
-		return codereview_disabled
+		raise hg_util.Abort(codereview_disabled)
 
 	# We already called this on startup but sometimes Mercurial forgets.
 	set_mercurial_encoding_to_utf8()
 	into the local repository.
 	"""
 	if codereview_disabled:
-		return codereview_disabled
+		raise hg_util.Abort(codereview_disabled)
 
 	if not opts["local"]:
 		err = hg_pull(ui, repo, update=True)
 	Uploads the current modifications for a given change to the server.
 	"""
 	if codereview_disabled:
-		return codereview_disabled
+		raise hg_util.Abort(codereview_disabled)
 
 	repo.ui.quiet = True
 	cl, err = LoadCL(ui, repo, name, web=True)

misc/cgo/test/cgo_test.go

 func TestSetEnv(t *testing.T)              { testSetEnv(t) }
 func TestHelpers(t *testing.T)             { testHelpers(t) }
 func TestLibgcc(t *testing.T)              { testLibgcc(t) }
+func Test1635(t *testing.T)                { test1635(t) }
+func TestPrintf(t *testing.T)              { testPrintf(t) }
 
 func BenchmarkCgoCall(b *testing.B) { benchCgoCall(b) }

misc/cgo/test/issue1560.go

 	}()
 }
 
+// wasteCPU starts a background goroutine to waste CPU 
+// to cause the power management to raise the CPU frequency. 
+// On ARM this has the side effect of making sleep more accurate.
+func wasteCPU() chan struct{} {
+	done := make(chan struct{})
+	go func() {
+		for {
+			select {
+			case <-done:
+				return
+			default:
+			}
+		}
+	}()
+	// pause for a short amount of time to allow the
+	// power management to recognise load has risen.
+	<-time.After(300 * time.Millisecond)
+	return done
+}
+
 func testParallelSleep(t *testing.T) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
+	defer close(wasteCPU())
+
 	sleepSec := 1
-	if runtime.GOARCH == "arm" {
-		// on ARM, the 1.3s deadline is frequently missed,
-		// so increase sleep time to 2s
-		sleepSec = 2
-	}
 	start := time.Now()
 	parallelSleep(sleepSec)
-	dt := time.Now().Sub(start)
+	dt := time.Since(start)
+	t.Logf("sleep(%d) slept for %v", sleepSec, dt)
 	// bug used to run sleeps in serial, producing a 2*sleepSec-second delay.
 	if dt >= time.Duration(sleepSec)*1300*time.Millisecond {
 		t.Fatalf("parallel %d-second sleeps slept for %f seconds", sleepSec, dt.Seconds())

misc/cgo/test/issue1635.go

+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cgotest
+
+/*
+// Mac OS X's gcc will generate scattered relocation 2/1 for
+// this function on Darwin/386, and 8l couldn't handle it.
+// this example is in issue 1635
+#include <stdio.h>
+void scatter() {
+	void *p = scatter;
+	printf("scatter = %p\n", p);
+}
+
+// this example is in issue 3253
+int hola = 0;
+int testHola() { return hola; }
+*/
+import "C"
+
+import "testing"
+
+func test1635(t *testing.T) {
+	C.scatter()
+	if v := C.hola; v != 0 {
+		t.Fatalf("C.hola is %d, should be 0", v)
+	}
+	if v := C.testHola(); v != 0 {
+		t.Fatalf("C.testHola() is %d, should be 0", v)
+	}
+}

misc/cgo/test/issue3945.go

+// Copyright 2012 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cgotest
+
+// Test that cgo reserves enough stack space during cgo call.
+// See http://golang.org/issue/3945 for details.
+
+// #include <stdio.h>
+//
+// void say() {
+//    printf("%s from C\n", "hello");
+// }
+//
+import "C"
+
+import "testing"
+
+func testPrintf(t *testing.T) {
+	C.say()
+}

misc/vim/autoload/go/complete.vim

 endif
 
 function! go#complete#Package(ArgLead, CmdLine, CursorPos)
-  let goroot = $GOROOT
-  if len(goroot) == 0
-    " should not occur.
-    return []
+  let dirs = []
+
+  if executable('go')
+      let goroot = substitute(system('go env GOROOT'), '\n', '', 'g')
+      if v:shell_error
+          echo '\'go env GOROOT\' failed'
+      endif
+  else
+      let goroot = $GOROOT
   endif
+
+  if len(goroot) != 0 && isdirectory(goroot)
+    let dirs += [ goroot ]
+  endif
+
+  let workspaces = split($GOPATH, ':')
+  if workspaces != []
+      let dirs += workspaces
+  endif
+
+  if len(dirs) == 0
+      " should not happen
+      return []
+  endif
+
   let ret = {}
-  let root = expand(goroot.'/pkg/'.s:goos.'_'.s:goarch)
-  for i in split(globpath(root, a:ArgLead.'*'), "\n")
-    if isdirectory(i)
-      let i .= '/'
-    elseif i !~ '\.a$'
-      continue
-    endif
-    let i = substitute(substitute(i[len(root)+1:], '[\\]', '/', 'g'), '\.a$', '', 'g')
-    let ret[i] = i
+  for dir in dirs
+    let root = expand(dir . '/pkg/' . s:goos . '_' . s:goarch)
+    for i in split(globpath(root, a:ArgLead.'*'), "\n")
+      if isdirectory(i)
+        let i .= '/'
+      elseif i !~ '\.a$'
+        continue
+      endif
+      let i = substitute(substitute(i[len(root)+1:], '[\\]', '/', 'g'), '\.a$', '', 'g')
+      let ret[i] = i
+    endfor
   endfor
   return sort(keys(ret))
 endfunction

misc/vim/plugin/godoc.vim

   if !len(word)
     let word = expand('<cword>')
   endif
-  let word = substitute(word, '[^a-zA-Z0-9\/]', '', 'g')
+  let word = substitute(word, '[^a-zA-Z0-9\\/._~-]', '', 'g')
   if !len(word)
     return
   endif
 EXTERN	int	dtype;
 EXTERN	int	tlsoffset;
 EXTERN	int	armsize;
+EXTERN	int	goarm;
 
 extern	char*	anames[];
 extern	Optab	optab[];
 {
 	int c;
 	char *p, *name, *val;
+	Sym *s;
 
 	Binit(&bso, 1, OWRITE);
 	listinit();
 	nuxiinit();
 	
 	p = getenv("GOARM");
-	if(p != nil && strcmp(p, "5") == 0)
+	if(p != nil)
+		goarm = atoi(p);
+	else
+		goarm = 7;
+	if(goarm == 5)
 		debug['F'] = 1;
 
 	ARGBEGIN {
 	cbp = buf.cbuf;
 	cbc = sizeof(buf.cbuf);
 
+	// embed goarm to runtime.goarm
+	s = lookup("runtime.goarm", 0);
+	s->dupok = 1;
+	adduint8(s, goarm);
+
 	addlibpath("command line", "command line", argv[0], "main");
 	loadlib();
 

src/cmd/6g/cgen.c

 agen(Node *n, Node *res)
 {
 	Node *nl, *nr;
-	Node n1, n2, n3, tmp, n4, n5;
+	Node n1, n2, n3, tmp, tmp2, n4, n5, nlen;
 	Prog *p1;
 	uint32 w;
 	uint64 v;
 
 	case OINDEX:
 		w = n->type->width;
+		// Generate the non-addressable child first.
 		if(nr->addable)
 			goto irad;
 		if(nl->addable) {
 			}
 			if(!isconst(nl, CTSTR)) {
 				regalloc(&n3, types[tptr], res);
-				agen(nl, &n3);
+				if(isfixedarray(nl->type))
+					agen(nl, &n3);
+				else {
+					igen(nl, &nlen, res);
+					nlen.type = types[tptr];
+					nlen.xoffset += Array_array;
+					gmove(&nlen, &n3);
+					nlen.type = types[TUINT32];
+					nlen.xoffset += Array_nel-Array_array;
+				}
 			}
 			goto index;
 		}
 		tempname(&tmp, nr->type);
 		cgen(nr, &tmp);
 		nr = &tmp;
-
 	irad:
 		if(!isconst(nl, CTSTR)) {
 			regalloc(&n3, types[tptr], res);
-			agen(nl, &n3);
+			if(isfixedarray(nl->type))
+				agen(nl, &n3);
+			else {
+				if(!nl->addable) {
+					// igen will need an addressable node.
+					tempname(&tmp2, nl->type);
+					cgen(nl, &tmp2);
+					nl = &tmp2;
+				}
+				igen(nl, &nlen, res);
+				nlen.type = types[tptr];
+				nlen.xoffset += Array_array;
+				gmove(&nlen, &n3);
+				nlen.type = types[TUINT32];
+				nlen.xoffset += Array_nel-Array_array;
+			}
 		}
 		if(!isconst(nr, CTINT)) {
 			regalloc(&n1, nr->type, N);
 	index:
 		// &a is in &n3 (allocated in res)
 		// i is in &n1 (if not constant)
+		// len(a) is in nlen (if needed)
 		// w is width
 
 		// explicit check for nil if array is large enough
 			v = mpgetfix(nr->val.u.xval);
 			if(isslice(nl->type) || nl->type->etype == TSTRING) {
 				if(!debug['B'] && !n->bounded) {
-					n1 = n3;
-					n1.op = OINDREG;
-					n1.type = types[tptr];
-					n1.xoffset = Array_nel;
 					nodconst(&n2, types[TUINT32], v);
-					gins(optoas(OCMP, types[TUINT32]), &n1, &n2);
+					gins(optoas(OCMP, types[TUINT32]), &nlen, &n2);
 					p1 = gbranch(optoas(OGT, types[TUINT32]), T, +1);
 					ginscall(panicindex, -1);
 					patch(p1, pc);
 				}
-
-				n1 = n3;
-				n1.op = OINDREG;
-				n1.type = types[tptr];
-				n1.xoffset = Array_array;
-				gmove(&n1, &n3);
+				regfree(&nlen);
 			}
 
 			if (v*w != 0)
 			if(is64(nr->type))
 				t = types[TUINT64];
 			if(isconst(nl, CTSTR)) {
-				nodconst(&n1, t, nl->val.u.sval->len);
+				nodconst(&nlen, t, nl->val.u.sval->len);
 			} else if(isslice(nl->type) || nl->type->etype == TSTRING) {
-				n1 = n3;
-				n1.op = OINDREG;
-				n1.type = types[TUINT32];
-				n1.xoffset = Array_nel;
 				if(is64(nr->type)) {
 					regalloc(&n5, t, N);
-					gmove(&n1, &n5);
-					n1 = n5;
+					gmove(&nlen, &n5);
+					regfree(&nlen);
+					nlen = n5;
 				}
 			} else {
-				nodconst(&n1, t, nl->type->bound);
+				nodconst(&nlen, t, nl->type->bound);
 			}
-			gins(optoas(OCMP, t), &n2, &n1);
+			gins(optoas(OCMP, t), &n2, &nlen);
 			p1 = gbranch(optoas(OLT, t), T, +1);
-			if(n5.op != OXXX)
-				regfree(&n5);
 			ginscall(panicindex, -1);
 			patch(p1, pc);
 		}
 			goto indexdone;
 		}
 
-		if(isslice(nl->type) || nl->type->etype == TSTRING) {
-			n1 = n3;
-			n1.op = OINDREG;
-			n1.type = types[tptr];
-			n1.xoffset = Array_array;
-			gmove(&n1, &n3);
-		}
-
 		if(w == 0) {
 			// nothing to do
 		} else if(w == 1 || w == 2 || w == 4 || w == 8) {
 		gmove(&n3, res);
 		regfree(&n2);
 		regfree(&n3);
+		if(!isconst(nl, CTSTR) && !isfixedarray(nl->type))
+			regfree(&nlen);
 		break;
 
 	case ONAME:

src/cmd/6g/ggen.c

 			// need to add numerator accounting for overflow
 			gins(optoas(OADD, nl->type), &n1, &dx);
 			nodconst(&n2, nl->type, 1);
-			gins(optoas(ORRC, nl->type), &n2, &dx);
+			gins(optoas(ORROTC, nl->type), &n2, &dx);
 			nodconst(&n2, nl->type, m.s-1);
 			gins(optoas(ORSH, nl->type), &n2, &dx);
 		} else {

src/cmd/6g/gsubr.c

 		a = ASARQ;
 		break;
 
-	case CASE(ORRC, TINT8):
-	case CASE(ORRC, TUINT8):
+	case CASE(ORROTC, TINT8):
+	case CASE(ORROTC, TUINT8):
 		a = ARCRB;
 		break;
 
-	case CASE(ORRC, TINT16):
-	case CASE(ORRC, TUINT16):
+	case CASE(ORROTC, TINT16):
+	case CASE(ORROTC, TUINT16):
 		a = ARCRW;
 		break;
 
-	case CASE(ORRC, TINT32):
-	case CASE(ORRC, TUINT32):
+	case CASE(ORROTC, TINT32):
+	case CASE(ORROTC, TUINT32):
 		a = ARCRL;
 		break;
 
-	case CASE(ORRC, TINT64):
-	case CASE(ORRC, TUINT64):
+	case CASE(ORROTC, TINT64):
+	case CASE(ORROTC, TUINT64):
 		a = ARCRQ;
 		break;
 

src/cmd/6g/peep.c

 #include "opt.h"
 
 static void	conprop(Reg *r);
+static void elimshortmov(Reg *r);
 static int prevl(Reg *r, int reg);
 static void pushback(Reg *r);
 static int regconsttyp(Adr*);
 		case AADCQ:
 		case ASBBL:
 		case ASBBQ:
+		case ARCRB:
+		case ARCRW:
 		case ARCRL:
 		case ARCRQ:
 			return 1;
+		case AADDB:
+		case AADDW:
 		case AADDL:
 		case AADDQ:
+		case ASUBB:
+		case ASUBW:
 		case ASUBL:
 		case ASUBQ:
 		case AJMP:
 		}
 	}
 	
+	// byte, word arithmetic elimination.
+	elimshortmov(r);
+
 	// constant propagation
 	// find MOV $con,R followed by
 	// another MOV $con,R without
 	return 0;
 }
 
+// movb elimination.
+// movb is simulated by the linker
+// when a register other than ax, bx, cx, dx
+// is used, so rewrite to other instructions
+// when possible.  a movb into a register
+// can smash the entire 32-bit register without
+// causing any trouble.
+static void
+elimshortmov(Reg *r)
+{
+	Prog *p;
+
+	for(r=firstr; r!=R; r=r->link) {
+		p = r->prog;
+		if(regtyp(&p->to)) {
+			switch(p->as) {
+			case AINCB:
+			case AINCW:
+				p->as = AINCQ;
+				break;
+			case ADECB:
+			case ADECW:
+				p->as = ADECQ;
+				break;
+			case ANEGB:
+			case ANEGW:
+				p->as = ANEGQ;
+				break;
+			case ANOTB:
+			case ANOTW:
+				p->as = ANOTQ;
+				break;
+			}
+			if(regtyp(&p->from) || p->from.type == D_CONST) {
+				// move or artihmetic into partial register.
+				// from another register or constant can be movl.
+				// we don't switch to 64-bit arithmetic if it can
+				// change how the carry bit is set (and the carry bit is needed).
+				switch(p->as) {
+				case AMOVB:
+				case AMOVW:
+					p->as = AMOVQ;
+					break;
+				case AADDB:
+				case AADDW:
+					if(!needc(p->link))
+						p->as = AADDQ;
+					break;
+				case ASUBB:
+				case ASUBW:
+					if(!needc(p->link))
+						p->as = ASUBQ;
+					break;
+				case AMULB:
+				case AMULW:
+					p->as = AMULQ;
+					break;
+				case AIMULB:
+				case AIMULW:
+					p->as = AIMULQ;
+					break;
+				case AANDB:
+				case AANDW:
+					p->as = AANDQ;
+					break;
+				case AORB:
+				case AORW:
+					p->as = AORQ;
+					break;
+				case AXORB:
+				case AXORW:
+					p->as = AXORQ;
+					break;
+				case ASHLB:
+				case ASHLW:
+					p->as = ASHLQ;
+					break;
+				}
+			} else {
+				// explicit zero extension
+				switch(p->as) {
+				case AMOVB:
+					p->as = AMOVBQZX;
+					break;
+				case AMOVW:
+					p->as = AMOVWQZX;
+					break;
+				}
+			}
+		}
+	}
+}
+
 int
 regconsttyp(Adr *a)
 {

src/cmd/6l/pass.c

 			}
 		}
 		if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd
-		|| HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd) {
+		|| HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd
+		|| HEADTYPE == Hplan9x64) {
 			// ELF uses FS instead of GS.
 			if(p->from.type == D_INDIR+D_GS)
 				p->from.type = D_INDIR+D_FS;
 			p = appendp(p);	// load g into CX
 			p->as = AMOVQ;
 			if(HEADTYPE == Hlinux || HEADTYPE == Hfreebsd
-			|| HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd)	// ELF uses FS
+			|| HEADTYPE == Hopenbsd || HEADTYPE == Hnetbsd
+			|| HEADTYPE == Hplan9x64)	// ELF uses FS
 				p->from.type = D_INDIR+D_FS;
 			else
 				p->from.type = D_INDIR+D_GS;

src/cmd/8g/cgen.c

 			break;
 		*a = *n;
 		return;
- 
+
 	case OCALLFUNC:
 		fp = structfirst(&flist, getoutarg(n->left->type));
 		cgen_call(n, 0);
 		return;
 	}
 
+	if (w == 8 || w == 12) {
+		if(componentgen(n, res))
+			return;
+	}
+
 	// offset on the stack
 	osrc = stkof(n);
 	odst = stkof(res);
 	}
 }
 
+static int
+cadable(Node *n)
+{
+	if(!n->addable) {
+		// dont know how it happens,
+		// but it does
+		return 0;
+	}
+
+	switch(n->op) {
+	case ONAME:
+		return 1;
+	}
+	return 0;
+}
+
+/*
+ * copy a structure component by component
+ * return 1 if can do, 0 if cant.
+ * nr is N for copy zero
+ */
+int
+componentgen(Node *nr, Node *nl)
+{
+	Node nodl, nodr;
+	int freel, freer;
+
+	freel = 0;
+	freer = 0;
+
+	switch(nl->type->etype) {
+	default:
+		goto no;
+
+	case TARRAY:
+		if(!isslice(nl->type))
+			goto no;
+	case TSTRING:
+	case TINTER:
+		break;
+	}
+
+	nodl = *nl;
+	if(!cadable(nl)) {
+		if(nr == N || !cadable(nr))
+			goto no;
+		igen(nl, &nodl, N);
+		freel = 1;
+	}
+
+	if(nr != N) {
+		nodr = *nr;
+		if(!cadable(nr)) {
+			igen(nr, &nodr, N);
+			freer = 1;
+		}
+	}
+
+	switch(nl->type->etype) {
+	case TARRAY:
+		if(!isslice(nl->type))
+			goto no;
+
+		nodl.xoffset += Array_array;
+		nodl.type = ptrto(nl->type->type);
+
+		if(nr != N) {
+			nodr.xoffset += Array_array;
+			nodr.type = nodl.type;
+		} else
+			nodconst(&nodr, nodl.type, 0);
+		gmove(&nodr, &nodl);
+
+		nodl.xoffset += Array_nel-Array_array;
+		nodl.type = types[TUINT32];
+
+		if(nr != N) {
+			nodr.xoffset += Array_nel-Array_array;
+			nodr.type = nodl.type;
+		} else
+			nodconst(&nodr, nodl.type, 0);
+		gmove(&nodr, &nodl);
+
+		nodl.xoffset += Array_cap-Array_nel;
+		nodl.type = types[TUINT32];
+
+		if(nr != N) {
+			nodr.xoffset += Array_cap-Array_nel;
+			nodr.type = nodl.type;
+		} else
+			nodconst(&nodr, nodl.type, 0);
+		gmove(&nodr, &nodl);
+
+		goto yes;
+
+	case TSTRING:
+		nodl.xoffset += Array_array;
+		nodl.type = ptrto(types[TUINT8]);
+
+		if(nr != N) {
+			nodr.xoffset += Array_array;
+			nodr.type = nodl.type;
+		} else
+			nodconst(&nodr, nodl.type, 0);
+		gmove(&nodr, &nodl);
+
+		nodl.xoffset += Array_nel-Array_array;
+		nodl.type = types[TUINT32];
+
+		if(nr != N) {
+			nodr.xoffset += Array_nel-Array_array;
+			nodr.type = nodl.type;
+		} else
+			nodconst(&nodr, nodl.type, 0);
+		gmove(&nodr, &nodl);
+
+		goto yes;
+
+	case TINTER:
+		nodl.xoffset += Array_array;
+		nodl.type = ptrto(types[TUINT8]);
+
+		if(nr != N) {
+			nodr.xoffset += Array_array;
+			nodr.type = nodl.type;
+		} else
+			nodconst(&nodr, nodl.type, 0);
+		gmove(&nodr, &nodl);
+
+		nodl.xoffset += Array_nel-Array_array;
+		nodl.type = ptrto(types[TUINT8]);
+
+		if(nr != N) {
+			nodr.xoffset += Array_nel-Array_array;
+			nodr.type = nodl.type;
+		} else
+			nodconst(&nodr, nodl.type, 0);
+		gmove(&nodr, &nodl);
+
+		goto yes;
+
+	case TSTRUCT:
+		goto no;
+	}
+
+no:
+	if(freer)
+		regfree(&nodr);
+	if(freel)
+		regfree(&nodl);
+	return 0;
+
+yes:
+	if(freer)
+		regfree(&nodr);
+	if(freel)
+		regfree(&nodl);
+	return 1;
+}